﻿///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2023, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////
#Область СлужебныйПрограммныйИнтерфейс

Процедура ОбновитьПрисоединенныйФайл(Знач ПрисоединенныйФайл, Знач ИнформацияОФайле) Экспорт

	РаботаСФайлами.ОбновитьФайл(ПрисоединенныйФайл, ИнформацияОФайле);

КонецПроцедуры

// См. функцию ДобавитьПрисоединенныйФайл в модуле РаботаСФайлами.
Функция ДобавитьФайл(ПараметрыФайла, Знач АдресФайлаВоВременномХранилище, Знач АдресВременногоХранилищаТекста = "",
	Знач Описание = "") Экспорт

	Возврат РаботаСФайлами.ДобавитьФайл(
		ПараметрыФайла, АдресФайлаВоВременномХранилище, АдресВременногоХранилищаТекста, Описание);

КонецФункции

// Получает данные файла и его двоичные данные.
//
// Параметры:
//  ФайлИлиВерсияСсылка - СправочникСсылка.Файлы
//                      - СправочникСсылка.ВерсииФайлов - файл или версия файла.
//  АдресПодписи - Строка - навигационная ссылка, содержащая адрес файла подписи во временном хранилище.
//  ИдентификаторФормы  - УникальныйИдентификатор - уникальный идентификатор формы.
//
// Возвращаемое значение:
//   Структура:
//     * ДанныеФайла - см. ДанныеФайла
//     * ДвоичныеДанные - ДвоичныеДанные
//     * ДвоичныеДанныеПодписи - ДвоичныеДанные
//
Функция ДанныеФайлаИДвоичныеДанные(ФайлИлиВерсияСсылка, АдресПодписи = Неопределено, ИдентификаторФормы = Неопределено) Экспорт

	МетаданныеОбъекта = Метаданные.НайтиПоТипу(ТипЗнч(ФайлИлиВерсияСсылка));
	ЭтоСправочникФайлов = ОбщегоНазначения.ЕстьРеквизитОбъекта("ВладелецФайла", МетаданныеОбъекта);
	ВозможностьХранитьВерсии = ОбщегоНазначения.ЕстьРеквизитОбъекта("ТекущаяВерсия", МетаданныеОбъекта);

	Если ВозможностьХранитьВерсии Тогда
		Если Не ЭтоСправочникФайлов Тогда
			РеквизитыФайлаИлиВерсии = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(ФайлИлиВерсияСсылка,
				"ТекущаяВерсия, Владелец");
		Иначе
			РеквизитыФайлаИлиВерсии = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(ФайлИлиВерсияСсылка, "ТекущаяВерсия");
		КонецЕсли;
	ИначеЕсли Не ЭтоСправочникФайлов Тогда
		РеквизитыФайлаИлиВерсии = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(ФайлИлиВерсияСсылка, "Владелец");
	КонецЕсли;

	ПараметрыДанныхФайла = РаботаСФайламиКлиентСервер.ПараметрыДанныхФайла();
	ПараметрыДанныхФайла.ПолучатьСсылкуНаДвоичныеДанные = Ложь;

	Если ВозможностьХранитьВерсии И ЗначениеЗаполнено(РеквизитыФайлаИлиВерсии.ТекущаяВерсия) Тогда

		ВерсияСсылка = РеквизитыФайлаИлиВерсии.ТекущаяВерсия;
		ДанныеФайла = ДанныеФайла(ФайлИлиВерсияСсылка, ВерсияСсылка, ПараметрыДанныхФайла);
	ИначеЕсли ЭтоСправочникФайлов Тогда
		ВерсияСсылка = ФайлИлиВерсияСсылка;
		ДанныеФайла = ДанныеФайла(ФайлИлиВерсияСсылка,, ПараметрыДанныхФайла);
	Иначе
		ВерсияСсылка = ФайлИлиВерсияСсылка;
		ДанныеФайла = ДанныеФайла(РеквизитыФайлаИлиВерсии.Владелец, ВерсияСсылка, ПараметрыДанныхФайла);
	КонецЕсли;

	ДвоичныеДанные = Неопределено;

	ТипХраненияФайла = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ВерсияСсылка, "ТипХраненияФайла");
	Если ТипХраненияФайла = Перечисления.ТипыХраненияФайлов.ВТомахНаДиске Тогда
		ДвоичныеДанные = РаботаСФайламиВТомахСлужебный.ДанныеФайла(ВерсияСсылка);
	Иначе
		ХранилищеФайла = РаботаСФайлами.ХранилищеФайлаИзИнформационнойБазы(ВерсияСсылка);
		ДвоичныеДанные = ХранилищеФайла.Получить();
	КонецЕсли;

	ДвоичныеДанныеПодписи = Неопределено;
	Если АдресПодписи <> Неопределено Тогда
		ДвоичныеДанныеПодписи = ПолучитьИзВременногоХранилища(АдресПодписи);
	КонецЕсли;

	Если ИдентификаторФормы <> Неопределено Тогда
		ДвоичныеДанные = ПоместитьВоВременноеХранилище(ДвоичныеДанные, ИдентификаторФормы);
	КонецЕсли;

	СтруктураВозврата = Новый Структура("ДанныеФайла, ДвоичныеДанные, ДвоичныеДанныеПодписи", ДанныеФайла,
		ДвоичныеДанные, ДвоичныеДанныеПодписи);

	Возврат СтруктураВозврата;

КонецФункции

// Создать папку файлов.
//
// Параметры:
//   Имя - Строка - имя папки
//   Родитель - ОпределяемыйТип.ВладелецПрисоединенныхФайлов - родительская папка.
//   Пользователь - СправочникСсылка.Пользователи - ответственный за папку.
//   ГруппаФайлов - ОпределяемыйТип.ПрисоединенныйФайл - группа (для иерархических справочников файлов).
//   РабочийКаталог - Строка - рабочий каталог папки в файловой системе.
//
// Возвращаемое значение:
//   СправочникСсылка.ПапкиФайлов.
//
Функция СоздатьПапкуФайлов(Имя, Родитель, Пользователь = Неопределено, ГруппаФайлов = Неопределено,
	РабочийКаталог = Неопределено) Экспорт

	Если ЭтоСправочникФайлы(Родитель) Тогда
		Папка = Справочники.ПапкиФайлов.СоздатьЭлемент();
		Папка.Ответственный = ?(Пользователь <> Неопределено, Пользователь, Пользователи.АвторизованныйПользователь());
		Папка.Родитель = Родитель;
	Иначе

		Папка = Справочники[РаботаСФайламиСлужебный.ИмяСправочникаХраненияФайлов(Родитель)].СоздатьГруппу();
		Если ТипЗнч(Папка.Ссылка) = ТипЗнч(Родитель) Тогда
			Папка.Родитель = ?(ГруппаФайлов = Неопределено, Родитель, ГруппаФайлов);
			Папка.ВладелецФайла = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Родитель, "ВладелецФайла");
		Иначе
			Папка.Родитель = ГруппаФайлов;
			Папка.ВладелецФайла = Родитель;
		КонецЕсли;

		Папка.Автор = ?(Пользователь <> Неопределено, Пользователь, Пользователи.АвторизованныйПользователь());

	КонецЕсли;
	Папка.Наименование = Имя;
	Папка.ДатаСоздания = ТекущаяДатаСеанса();
	Папка.Заполнить(Неопределено);
	Папка.Записать();

	Если ЗначениеЗаполнено(РабочийКаталог) Тогда
		РаботаСФайламиСлужебный.СохранитьРабочийКаталогПапки(Папка.Ссылка, РабочийКаталог);
	КонецЕсли;

	Возврат Папка.Ссылка;

КонецФункции

// Создает файл в ИБ вместе с версией.
//
// Параметры:
//   Владелец       - СправочникСсылка.ПапкиФайлов
//                  - ЛюбаяСсылка - будет установлен в реквизит ВладелецФайла у
//                    созданного файла.
//   СведенияОФайле - см. РаботаСФайламиКлиентСервер.СведенияОФайле
//
// Возвращаемое значение:
//    СправочникСсылка.Файлы - созданный файл.
//
Функция СоздатьФайлСВерсией(ВладелецФайла, СведенияОФайле) Экспорт

	НачатьТранзакцию();
	Попытка

		ФайлСсылка = СоздатьФайл(ВладелецФайла, СведенияОФайле);
		Версия = Справочники.ВерсииФайлов.ПустаяСсылка();
		Если СведенияОФайле.ХранитьВерсии Тогда
			Версия = РаботаСФайламиСлужебный.СоздатьВерсию(ФайлСсылка, СведенияОФайле);
		КонецЕсли;
		РаботаСФайламиСлужебный.ОбновитьВерсиюВФайле(ФайлСсылка, Версия, СведенияОФайле.АдресВременногоХранилищаТекста);

		Если Не ЗначениеЗаполнено(СведенияОФайле.Кодировка) Тогда
			СведенияОФайле.Кодировка = РаботаСФайламиСлужебныйКлиентСервер.ОпределитьКодировкуДвоичныхДанных(
				СведенияОФайле.АдресВременногоХранилищаФайла, СведенияОФайле.РасширениеБезТочки);
		КонецЕсли;

		Если СведенияОФайле.Кодировка <> Неопределено Тогда
			РегистрыСведений.КодировкиФайлов.ЗаписатьКодировкуВерсииФайла(
				?(Версия = Справочники.ВерсииФайлов.ПустаяСсылка(), ФайлСсылка, Версия), СведенияОФайле.Кодировка);
		КонецЕсли;

		ЕстьПравоСохранения = ПравоДоступа("СохранениеДанныхПользователя", Метаданные);
		Если СведенияОФайле.ЗаписатьВИсторию И ЕстьПравоСохранения Тогда
			НавигационнаяСсылкаФайла = ПолучитьНавигационнуюСсылку(ФайлСсылка);
			ИсторияРаботыПользователя.Добавить(НавигационнаяСсылкаФайла);
		КонецЕсли;

		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		ВызватьИсключение;
	КонецПопытки;

	РаботаСФайламиПереопределяемый.ПриСозданииФайла(ФайлСсылка);
	Возврат ФайлСсылка;

КонецФункции

// Освобождает файл.
//
// Параметры:
//   ДанныеФайла - см. ДанныеФайла.
//   УникальныйИдентификатор - УникальныйИдентификатор - уникальный идентификатор формы.
//
Процедура ОсвободитьФайл(ДанныеФайла, УникальныйИдентификатор = Неопределено) Экспорт

	НачатьТранзакцию();
	Попытка
		БлокировкаДанных = Новый БлокировкаДанных;
		ЭлементБлокировкиДанных = БлокировкаДанных.Добавить(Метаданные.НайтиПоТипу(ТипЗнч(
			ДанныеФайла.Ссылка)).ПолноеИмя());
		ЭлементБлокировкиДанных.УстановитьЗначение("Ссылка", ДанныеФайла.Ссылка);
		БлокировкаДанных.Заблокировать();

		ФайлОбъект = ДанныеФайла.Ссылка.ПолучитьОбъект();

		ЗаблокироватьДанныеДляРедактирования(ФайлОбъект.Ссылка,, УникальныйИдентификатор);
		ФайлОбъект.Редактирует = Справочники.Пользователи.ПустаяСсылка();
		ФайлОбъект.ДатаЗаема = Дата("00010101000000");
		ФайлОбъект.Записать();

		РаботаСФайламиПереопределяемый.ПриОсвобожденииФайла(ДанныеФайла, УникальныйИдентификатор);
		РазблокироватьДанныеДляРедактирования(ДанныеФайла.Ссылка, УникальныйИдентификатор);
		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		РазблокироватьДанныеДляРедактирования(ДанныеФайла.Ссылка, УникальныйИдентификатор);
		ВызватьИсключение;
	КонецПопытки;

КонецПроцедуры

Функция ОсвободитьФайлы(Знач Файлы) Экспорт

	ВерсииФайлов = Новый Соответствие;

	ПараметрыДанныхФайла = РаботаСФайламиКлиентСервер.ПараметрыДанныхФайла();
	ПараметрыДанныхФайла.ПолучатьСсылкуНаДвоичныеДанные = Ложь;

	Для Каждого ПрисоединенныйФайл Из Файлы Цикл
		РаботаСФайламиСлужебный.ОсвободитьФайл(ПрисоединенныйФайл);
		ДанныеФайла = ДанныеФайла(ПрисоединенныйФайл,, ПараметрыДанныхФайла);
		ВерсииФайлов.Вставить(ПрисоединенныйФайл, ДанныеФайла.ТекущаяВерсия);
	КонецЦикла;

	Результат = Новый Структура;
	Результат.Вставить("КоличествоЗанятыхФайлов", РаботаСФайламиСлужебный.КоличествоЗанятыхФайлов());
	Результат.Вставить("ВерсииФайлов", ВерсииФайлов);
	Возврат Результат;

КонецФункции

// Занять файл на редактирование.
//
// Параметры:
//  ДанныеФайла  - Структура - выходной параметр.
//  СтрокаОшибки - Строка - в которой возвращается причина ошибки в случае неуспеха, например,
//                          "Файл занят другим пользователем".
//  ДополнительныеПараметры - см. РаботаСФайламиСлужебныйКлиентСервер.ПараметрыЗанятияФайла
//
//
// Возвращаемое значение:
//   Булево  - успешно ли выполнена операция.
//
Функция ЗанятьФайл(ДанныеФайла, СтрокаОшибки = "", ДополнительныеПараметры = Неопределено) Экспорт

	Если ДополнительныеПараметры = Неопределено Тогда
		ДополнительныеПараметры = РаботаСФайламиСлужебныйКлиентСервер.ПараметрыЗанятияФайла();
	КонецЕсли;

	СтрокаОшибки = "";
	РаботаСФайламиПереопределяемый.ПриПопыткеЗанятьФайл(ДанныеФайла, СтрокаОшибки);
	Если Не ПустаяСтрока(СтрокаОшибки) Тогда
		Возврат Ложь;
	КонецЕсли;

	НачатьТранзакцию();
	Попытка
		БлокировкаДанных = Новый БлокировкаДанных;
		ЭлементБлокировкиДанных = БлокировкаДанных.Добавить(Метаданные.НайтиПоТипу(ТипЗнч(
			ДанныеФайла.Ссылка)).ПолноеИмя());
		ЭлементБлокировкиДанных.УстановитьЗначение("Ссылка", ДанныеФайла.Ссылка);
		БлокировкаДанных.Заблокировать();

		ФайлОбъект = ДанныеФайла.Ссылка.ПолучитьОбъект();

		ЗаблокироватьДанныеДляРедактирования(ФайлОбъект.Ссылка,, ДополнительныеПараметры.УникальныйИдентификатор);
		Если ДополнительныеПараметры.Пользователь = Неопределено Тогда
			ФайлОбъект.Редактирует = Пользователи.АвторизованныйПользователь();
		Иначе
			ФайлОбъект.Редактирует = ДополнительныеПараметры.Пользователь;
		КонецЕсли;
		Если ТипЗнч(ДополнительныеПараметры.ДополнительныеСвойства) = Тип("Структура") Тогда
			ОбщегоНазначенияКлиентСервер.ДополнитьСтруктуру(ФайлОбъект.ДополнительныеСвойства,
				ДополнительныеПараметры.ДополнительныеСвойства, Ложь);
		КонецЕсли;
		ФайлОбъект.ДатаЗаема = ТекущаяДатаСеанса();
		ФайлОбъект.Записать();

		НавигационнаяСсылкаТекущейВерсии = ДанныеФайла.НавигационнаяСсылкаТекущейВерсии;
		РабочийКаталогВладельца = ДанныеФайла.РабочийКаталогВладельца;

		ПараметрыДанныхФайла = РаботаСФайламиКлиентСервер.ПараметрыДанныхФайла();
		ПараметрыДанныхФайла.ВызыватьИсключение = ДополнительныеПараметры.ВызыватьИсключение;

		ДанныеФайла = ДанныеФайла(ДанныеФайла.Ссылка, ?(ДанныеФайла.Версия = ДанныеФайла.Ссылка, Неопределено,
			ДанныеФайла.Версия), ПараметрыДанныхФайла);
		ДанныеФайла.НавигационнаяСсылкаТекущейВерсии = НавигационнаяСсылкаТекущейВерсии;
		ДанныеФайла.РабочийКаталогВладельца = РабочийКаталогВладельца;

		РаботаСФайламиПереопределяемый.ПриЗахватеФайла(ДанныеФайла, ДополнительныеПараметры.УникальныйИдентификатор);

		РазблокироватьДанныеДляРедактирования(ДанныеФайла.Ссылка, ДополнительныеПараметры.УникальныйИдентификатор);
		ЗафиксироватьТранзакцию();

	Исключение
		ОтменитьТранзакцию();
		РазблокироватьДанныеДляРедактирования(ДанныеФайла.Ссылка, ДополнительныеПараметры.УникальныйИдентификатор);
		ВызватьИсключение;
	КонецПопытки;

	Возврат Истина;

КонецФункции

// Возвращает массив структур или структуру (в зависимости от переданных данных), 
// содержащих различные сведения о файле.
//
// Параметры:
//  Файлы  - Массив из:
//         - СправочникСсылка.Файлы
//  ИдентификаторФормы             - УникальныйИдентификатор - уникальный идентификатор формы, во временное хранилище
//                                 которой надо поместить файл и вернуть адрес в свойстве СсылкаНаДвоичныеДанныеФайла.
//
// Возвращаемое значение:
//  - Массив из см. РаботаСФайлами.ДанныеФайла
//      см. РаботаСФайлами.ДанныеФайла
//   
//
Функция ДанныеФайловДляПодписания(Знач Файлы, ИдентификаторФормы = Неопределено) Экспорт

	Если ТипЗнч(Файлы) <> Тип("Массив") Тогда
		ПараметрыДанныхФайла = РаботаСФайламиКлиентСервер.ПараметрыДанныхФайла();
		ПараметрыДанныхФайла.ИдентификаторФормы = ИдентификаторФормы;
		Возврат ДанныеФайла(Файлы,, ПараметрыДанныхФайла);
	КонецЕсли;

	ПараметрыДанныхФайла = РаботаСФайламиКлиентСервер.ПараметрыДанныхФайла();
	ПараметрыДанныхФайла.ИдентификаторФормы = ИдентификаторФормы;

	ДанныеФайлов = Новый Массив;
	Для Каждого Файл Из Файлы Цикл
		ДанныеФайлов.Добавить(ДанныеФайла(Файл,, ПараметрыДанныхФайла));
	КонецЦикла;

	Возврат ДанныеФайлов;

КонецФункции

// Возвращает структуру, содержащую различные сведения о файле и версии.
// 
// Параметры: 
//  ФайлСсылка - см. РаботаСФайлами.ДвоичныеДанныеФайла.ПрисоединенныйФайл.
//  ВерсияСсылка - СправочникСсылка.ВерсииФайлов - версия файла по которой формируются данные, если не указан то по
//                                                 текущей версии или файлу.
//  ПараметрыДанныхФайла - см. РаботаСФайламиКлиентСервер.ПараметрыДанныхФайла.
// 
// Возвращаемое значение:
//  Структура:
//   * Автор - СправочникСсылка.Пользователи
//   * АвторТекущейВерсии - СправочникСсылка.Пользователи
//   * ВРабочемКаталогеНаЧтение - Булево
//   * Версия - СправочникСсылка.ВерсииФайлов
//   * Владелец - ОпределяемыйТип.ВладелецПрисоединенныхФайлов
//   * ДатаЗаема - Дата
//   * ДатаМодификацииУниверсальная - Дата
//   * Зашифрован	- Булево
//   * Кодировка - Строка
//   * КодировкаТекущейВерсии - Строка
//   * НаЧтение - Булево
//   * НавигационнаяСсылка - Строка
//   * НавигационнаяСсылкаТекущейВерсии - Строка
//   * Наименование - Строка
//   * НомерВерсии - Число
//   * ПапкаДляСохранитьКак - Строка
//   * ПодписанЭП - Булево
//   * ПолноеИмяФайлаВРабочемКаталоге - Строка
//   * ПолноеНаименованиеВерсии - Строка
//   * ПометкаУдаления - Булево
//   * РабочийКаталогВладельца - Строка
//   * Размер - Число
//   * Расширение - Строка
//   * Редактирует - СправочникСсылка.Пользователи
//   * Служебный - Булево
//   * Ссылка - ОпределяемыйТип.ПрисоединенныйФайл
//   * СсылкаНаДвоичныеДанныеФайла - Строка
//   * СтатусИзвлеченияТекста - Строка
//   * ТекущаяВерсия - СправочникСсылка.ВерсииФайлов
//   * Том - СправочникСсылка.ТомаХраненияФайлов
//   * ФайлРедактируетТекущийПользователь - Булево
//   * ХранитьВерсии - Булево
//
Функция ДанныеФайла(ФайлСсылка, ВерсияСсылка = Неопределено, ПараметрыДанныхФайла = Неопределено) Экспорт

	Если ПараметрыДанныхФайла = Неопределено Тогда
		ПараметрыДанныхФайла = РаботаСФайламиКлиентСервер.ПараметрыДанныхФайла();
	КонецЕсли;

	ИдентификаторФормы = ПараметрыДанныхФайла.ИдентификаторФормы;
	ВызыватьИсключение = ПараметрыДанныхФайла.ВызыватьИсключение;
	ПолучатьСсылкуНаДвоичныеДанные = ПараметрыДанныхФайла.ПолучатьСсылкуНаДвоичныеДанные;

	ЕстьПраваНаОбъект = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(ФайлСсылка, "Ссылка", Истина);

	Если ЕстьПраваНаОбъект = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;
	ОбновлениеИнформационнойБазы.ПроверитьОбъектОбработан(ФайлСсылка);

	ФайлОбъект = ФайлСсылка.ПолучитьОбъект();

	ДанныеФайла = Новый Структура;
	ДанныеФайла.Вставить("Ссылка", ФайлОбъект.Ссылка);
	ДанныеФайла.Вставить("Редактирует", ФайлОбъект.Редактирует);
	ДанныеФайла.Вставить("Владелец", ФайлОбъект.ВладелецФайла);

	МетаданныеОбъектаФайла = Метаданные.НайтиПоТипу(ТипЗнч(ФайлСсылка));

	Если ОбщегоНазначения.ЕстьРеквизитОбъекта("ТекущаяВерсия", МетаданныеОбъектаФайла) И ЗначениеЗаполнено(
		ФайлСсылка.ТекущаяВерсия) Тогда
		ТекущаяВерсияФайла = ФайлОбъект.ТекущаяВерсия;
	Иначе
		ТекущаяВерсияФайла = ФайлСсылка;
	КонецЕсли;

	Если ВерсияСсылка <> Неопределено Тогда
		ДанныеФайла.Вставить("Версия", ВерсияСсылка);
	Иначе
		ДанныеФайла.Вставить("Версия", ТекущаяВерсияФайла);
	КонецЕсли;

	ДанныеФайла.Вставить("ТекущаяВерсия", ТекущаяВерсияФайла);
	ДанныеФайла.Вставить("ХранитьВерсии", ФайлОбъект.ХранитьВерсии);
	ДанныеФайла.Вставить("ПометкаУдаления", ФайлОбъект.ПометкаУдаления);
	ДанныеФайла.Вставить("Зашифрован", ФайлОбъект.Зашифрован);
	ДанныеФайла.Вставить("ПодписанЭП", ФайлОбъект.ПодписанЭП);
	ДанныеФайла.Вставить("ДатаЗаема", ФайлОбъект.ДатаЗаема);

	Если ВерсияСсылка = Неопределено Тогда
		Если ПолучатьСсылкуНаДвоичныеДанные Тогда
			СсылкаНаДвоичныеДанныеФайла = ПоместитьВоВременноеХранилище(РаботаСФайлами.ДвоичныеДанныеФайла(
				ТекущаяВерсияФайла, ВызыватьИсключение), ИдентификаторФормы);
		Иначе
			СсылкаНаДвоичныеДанныеФайла = Неопределено;
		КонецЕсли;
		ДанныеФайла.Вставить("СсылкаНаДвоичныеДанныеФайла", СсылкаНаДвоичныеДанныеФайла);

		ДанныеФайла.Вставить("НавигационнаяСсылка", ПолучитьНавигационнуюСсылку(ФайлСсылка));
		ДанныеФайла.Вставить("АвторТекущейВерсии", ФайлСсылка.Изменил);
		ДанныеФайла.Вставить("Кодировка", РегистрыСведений.КодировкиФайлов.ОпределитьКодировкуФайла(ТекущаяВерсияФайла,
			ФайлОбъект.Расширение));
	Иначе
		Если ПолучатьСсылкуНаДвоичныеДанные Тогда
			СсылкаНаДвоичныеДанныеФайла = ПоместитьВоВременноеХранилище(РаботаСФайлами.ДвоичныеДанныеФайла(
				ВерсияСсылка, ВызыватьИсключение), ИдентификаторФормы);
		Иначе
			СсылкаНаДвоичныеДанныеФайла = Неопределено;
		КонецЕсли;
		ДанныеФайла.Вставить("СсылкаНаДвоичныеДанныеФайла", СсылкаНаДвоичныеДанныеФайла);

		ДанныеФайла.Вставить("НавигационнаяСсылка", ПолучитьНавигационнуюСсылку(ФайлОбъект.Ссылка));
		ДанныеФайла.Вставить("АвторТекущейВерсии", ВерсияСсылка.Автор);
		ДанныеФайла.Вставить("Кодировка", РегистрыСведений.КодировкиФайлов.ОпределитьКодировкуФайла(ВерсияСсылка,
			ФайлОбъект.Расширение));
	КонецЕсли;

	Если ДанныеФайла.Зашифрован Тогда

		Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ЭлектроннаяПодпись") Тогда
			МодульЭлектроннаяПодпись = ОбщегоНазначения.ОбщийМодуль("ЭлектроннаяПодпись");
			МассивСертификатовШифрования = МодульЭлектроннаяПодпись.СертификатыШифрования(ДанныеФайла.Ссылка);
		Иначе
			МассивСертификатовШифрования = Неопределено;
		КонецЕсли;

		ДанныеФайла.Вставить("МассивСертификатовШифрования", МассивСертификатовШифрования);

	КонецЕсли;

	ДанныеФайла.Вставить("Служебный", Ложь);
	Если ОбщегоНазначенияКлиентСервер.ЕстьРеквизитИлиСвойствоОбъекта(ФайлОбъект, "Служебный") Тогда
		ДанныеФайла.Служебный = ФайлОбъект.Служебный;
	КонецЕсли;

	РаботаСФайламиСлужебный.ЗаполнитьДополнительныеДанныеФайла(ДанныеФайла, ФайлОбъект, ВерсияСсылка);
	Возврат ДанныеФайла;

КонецФункции

Функция ПолучитьДанныеФайла(Знач ПрисоединенныйФайл, Знач ИдентификаторФормы = Неопределено,
	Знач ПолучатьСсылкуНаДвоичныеДанные = Истина, Знач ДляРедактирования = Ложь) Экспорт

	Возврат РаботаСФайлами.ДанныеФайла(ПрисоединенныйФайл, ИдентификаторФормы, ПолучатьСсылкуНаДвоичныеДанные,
		ДляРедактирования);
КонецФункции

Функция ДанныеФайлаДляПечати(Знач ПрисоединенныйФайл, Знач ИдентификаторФормы = Неопределено) Экспорт

	ДанныеФайла = ПолучитьДанныеФайла(ПрисоединенныйФайл, ИдентификаторФормы);
	Расширение = НРег(ДанныеФайла.Расширение);
	Если Расширение = "mxl" Тогда
		ДвоичныеДанныеФайла = ПолучитьИзВременногоХранилища(ДанныеФайла.СсылкаНаДвоичныеДанныеФайла); // ДвоичныеДанные
		ИмяВременногоФайла = ПолучитьИмяВременногоФайла();
		ДвоичныеДанныеФайла.Записать(ИмяВременногоФайла);
		ТабличныйДокумент = Новый ТабличныйДокумент;
		ТабличныйДокумент.Прочитать(ИмяВременногоФайла);
		УстановленБезопасныйРежим = БезопасныйРежим() <> Ложь;

		Если ТипЗнч(УстановленБезопасныйРежим) = Тип("Строка") Тогда
			УстановленБезопасныйРежим = Истина;
		КонецЕсли;

		Если Не УстановленБезопасныйРежим Тогда
			УдалитьФайлы(ИмяВременногоФайла);
		КонецЕсли;
		ДанныеФайла.Вставить("ТабличныйДокумент", ТабличныйДокумент);
	КонецЕсли;

	Возврат ДанныеФайла;

КонецФункции

// Возвращает сведения о файле и версии.
// 
// Параметры:
//  ФайлСсылка - СправочникСсылка.Файлы
//  ВерсияСсылка - СправочникСсылка.ВерсииФайлов
//  ИдентификаторФормы - УникальныйИдентификатор
//  РабочийКаталогВладельца - Строка
//  ПредыдущийАдресФайла - Строка
// 
// Возвращаемое значение:
//   см. ДанныеФайла
//
Функция ДанныеФайлаДляОткрытия(ФайлСсылка, ВерсияСсылка, ИдентификаторФормы = Неопределено,
	РабочийКаталогВладельца = Неопределено, ПредыдущийАдресФайла = Неопределено) Экспорт

	ЕстьПраваНаОбъект = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(ФайлСсылка, "Ссылка", Истина);
	Если ЕстьПраваНаОбъект = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;

	Если ПредыдущийАдресФайла <> Неопределено Тогда
		Если Не ПустаяСтрока(ПредыдущийАдресФайла) И ЭтоАдресВременногоХранилища(ПредыдущийАдресФайла) Тогда
			УдалитьИзВременногоХранилища(ПредыдущийАдресФайла);
		КонецЕсли;
	КонецЕсли;

	Если Не ЗначениеЗаполнено(ВерсияСсылка) И ОбщегоНазначения.ЕстьРеквизитОбъекта("ТекущаяВерсия",
		Метаданные.НайтиПоТипу(ТипЗнч(ФайлСсылка))) Тогда

		ТекущаяВерсия = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ФайлСсылка, "ТекущаяВерсия");
		Если ЗначениеЗаполнено(ТекущаяВерсия) Тогда
			ВерсияСсылка = ТекущаяВерсия;
		КонецЕсли;
	КонецЕсли;

	ПараметрыДанныхФайла = РаботаСФайламиКлиентСервер.ПараметрыДанныхФайла();
	ПараметрыДанныхФайла.ИдентификаторФормы = ИдентификаторФормы;

	ДанныеФайла = ДанныеФайла(ФайлСсылка, ВерсияСсылка, ПараметрыДанныхФайла);
	Если РабочийКаталогВладельца = Неопределено Тогда
		РабочийКаталогВладельца = РабочийКаталогПапки(ДанныеФайла.Владелец);
	КонецЕсли;
	ДанныеФайла.Вставить("РабочийКаталогВладельца", РабочийКаталогВладельца);

	Если ДанныеФайла.РабочийКаталогВладельца <> "" Тогда
		ИмяФайла = ОбщегоНазначенияКлиентСервер.ПолучитьИмяСРасширением(
			ДанныеФайла.ПолноеНаименованиеВерсии, ДанныеФайла.Расширение);
		ОбщегоНазначения.СократитьИмяФайла(ИмяФайла);
		ПолноеИмяФайлаВРабочемКаталоге = РабочийКаталогВладельца + ИмяФайла;
		ДанныеФайла.Вставить("ПолноеИмяФайлаВРабочемКаталоге", ПолноеИмяФайлаВРабочемКаталоге);
	КонецЕсли;

	СведенияОВерсии = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(ДанныеФайла.Версия,
		"ТипХраненияФайла, Том, ПутьКФайлу");

	Если ДанныеФайла.Версия <> Неопределено И СведенияОВерсии.ТипХраненияФайла
		= Перечисления.ТипыХраненияФайлов.ВТомахНаДиске Тогда

		ДвоичныеДанные = РаботаСФайламиВТомахСлужебный.ДанныеФайла(ДанныеФайла.Версия);
		ДанныеФайла.НавигационнаяСсылкаТекущейВерсии = ПоместитьВоВременноеХранилище(ДвоичныеДанные, ИдентификаторФормы);

	КонецЕсли;

	ПредыдущийАдресФайла = ДанныеФайла.НавигационнаяСсылкаТекущейВерсии;
	Возврат ДанныеФайла;

КонецФункции

Функция ДанныеОбновленияПоляИзображения(ФайлСсылка, ПараметрыПолученияДанных) Экспорт

	ДанныеФайла = ?(ЗначениеЗаполнено(ФайлСсылка), ПолучитьДанныеФайла(ФайлСсылка, ПараметрыПолученияДанных),
		Неопределено);

	ДанныеОбновления = Новый Структура;
	ДанныеОбновления.Вставить("ДанныеФайла", ДанныеФайла);
	ДанныеОбновления.Вставить("ЦветТекста", ЦветаСтиля.ЦветТекстаНевыбраннойКартинки);
	ДанныеОбновления.Вставить("ФайлПоврежден", Ложь);

	Если ДанныеФайла <> Неопределено И ПолучитьИзВременногоХранилища(ДанныеФайла.СсылкаНаДвоичныеДанныеФайла)
		= Неопределено Тогда

		ДанныеОбновления.ФайлПоврежден = Истина;
		ДанныеОбновления.ЦветТекста    = ЦветаСтиля.ПоясняющийОшибкуТекст;

	КонецЕсли;

	Возврат ДанныеОбновления;

КонецФункции

Процедура ОпределитьФормуПрисоединенногоФайла(Источник, ВидФормы, Параметры, ВыбраннаяФорма, ДополнительнаяИнформация,
	СтандартнаяОбработка) Экспорт

	ЭтоФормаВерсии = Ложь;

	Если Источник <> Неопределено Тогда
		ЭтоФормаВерсии = ОбщегоНазначения.ЕстьРеквизитОбъекта("РодительскаяВерсия", Метаданные.НайтиПоТипу(ТипЗнч(
			Источник)));
	КонецЕсли;

	Если ВидФормы = "ФормаГруппы" Тогда
		ВыбраннаяФорма = "Обработка.РаботаСФайлами.Форма.ГруппаФайлов";
		СтандартнаяОбработка = Ложь;
	ИначеЕсли ВидФормы = "ФормаОбъекта" Тогда

		Если Не ЭтоФормаВерсии Тогда
			ВыбраннаяФорма = "Обработка.РаботаСФайлами.Форма.ПрисоединенныйФайл";
			СтандартнаяОбработка = Ложь;
		КонецЕсли;

	ИначеЕсли ВидФормы = "ФормаСписка" Тогда

		Если Не ЭтоФормаВерсии Тогда
			ВыбраннаяФорма = "Обработка.РаботаСФайлами.Форма.ПрисоединенныеФайлы";
			СтандартнаяОбработка = Ложь;
		КонецЕсли;

	КонецЕсли;

КонецПроцедуры

Функция КоличествоПрисоединенныхФайлов(ВладелецФайлов, ВозвращатьДанныеФайлов = Ложь,
	РеквизитРазмещения = Неопределено) Экспорт

	ФайлыВладельца = Новый Структура;
	ФайлыВладельца.Вставить("КоличествоФайлов", 0);
	ФайлыВладельца.Вставить("ДанныеФайла", Неопределено);

	ИмяСправочникаХранения = РаботаСФайламиСлужебный.ИмяСправочникаХраненияФайлов(ВладелецФайлов);
	Если ЗначениеЗаполнено(ИмяСправочникаХранения) Тогда

		ТекстЗапроса =
		"ВЫБРАТЬ РАЗРЕШЕННЫЕ РАЗЛИЧНЫЕ
		|	СправочникХраненияФайлов.Ссылка КАК Файл
		|ИЗ
		|	&ИмяСправочника КАК СправочникХраненияФайлов
		|ГДЕ
		|	СправочникХраненияФайлов.ВладелецФайла = &ВладелецФайла
		|	И НЕ СправочникХраненияФайлов.ПометкаУдаления
		|	И &ЭтоГруппа = ЛОЖЬ
		|	И &Служебный = ЛОЖЬ";
		ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ИмяСправочника", "Справочник." + ИмяСправочникаХранения);

		ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&Служебный", ?(РаботаСФайламиСлужебный.ЕстьРеквизитСлужебный(
			ИмяСправочникаХранения), "СправочникХраненияФайлов.Служебный", "ЛОЖЬ"));

		ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ЭтоГруппа", ?(
			Метаданные.Справочники[ИмяСправочникаХранения].Иерархический, "СправочникХраненияФайлов.ЭтоГруппа", "ЛОЖЬ"));

		Запрос = Новый Запрос(ТекстЗапроса);
		Запрос.УстановитьПараметр("ВладелецФайла", ВладелецФайлов);
		ТаблицаФайлов = Запрос.Выполнить().Выгрузить();
		КоличествоФайлов = ТаблицаФайлов.Количество();

		ФайлыВладельца.КоличествоФайлов = КоличествоФайлов;

		ПараметрыДанныхФайла = РаботаСФайламиКлиентСервер.ПараметрыДанныхФайла();
		ПараметрыДанныхФайла.ПолучатьСсылкуНаДвоичныеДанные = Ложь;
		ПараметрыДанныхФайла.ВызыватьИсключение = Ложь;

		Если ВозвращатьДанныеФайлов И КоличествоФайлов > 0 Тогда
			Если РеквизитРазмещения = Неопределено Или Не ЗначениеЗаполнено(ВладелецФайлов[РеквизитРазмещения]) Тогда
				ФайлыВладельца.ДанныеФайла = ДанныеФайла(ТаблицаФайлов[0].Файл,, ПараметрыДанныхФайла);
			Иначе
				ФайлыВладельца.ДанныеФайла = ДанныеФайла(ВладелецФайлов[РеквизитРазмещения],, ПараметрыДанныхФайла);
			КонецЕсли;
		КонецЕсли;

	КонецЕсли;

	Возврат ?(ВозвращатьДанныеФайлов, ФайлыВладельца, ФайлыВладельца.КоличествоФайлов);

КонецФункции

Функция ЭтоЭлементРаботаСФайлами(ЭлементДанных) Экспорт
	Возврат РаботаСФайламиСлужебный.ЭтоЭлементРаботаСФайлами(ЭлементДанных);
КонецФункции

Функция НовыйТабличныйДокументНаСервере(КоличествоСтраниц) Экспорт
	ТабличныйДокумент =Новый ТабличныйДокумент;
	ПустаяОбласть = ТабличныйДокумент.ПолучитьОбласть(1, 1, 1, 1);
	Для ИндексОбъекта = 1 По КоличествоСтраниц Цикл
		ТабличныйДокумент.Вывести(ПустаяОбласть);
		ТабличныйДокумент.ВывестиГоризонтальныйРазделительСтраниц();
	КонецЦикла;
	Возврат ТабличныйДокумент;
КонецФункции

Процедура ЗаполнитьНастройкиСканирования(ПараметрыСканирования, ИдентификаторКлиента) Экспорт

	НастройкиСканированияПользователя = РаботаСФайлами.ПолучитьНастройкиСканированияПользователя(ИдентификаторКлиента);
	ЗаполнитьЗначенияСвойств(ПараметрыСканирования, НастройкиСканированияПользователя);

КонецПроцедуры

Функция ПолучитьНастройкиСканированияПользователя(ИдентификаторКлиента) Экспорт
	Возврат РаботаСФайлами.ПолучитьНастройкиСканированияПользователя(ИдентификаторКлиента);
КонецФункции

Процедура СохранитьНастройкиСканированияПользователя(НастройкиСканированияКлиента, ИдентификаторКлиента) Экспорт
	РаботаСФайлами.СохранитьНастройкиСканированияПользователя(НастройкиСканированияКлиента, ИдентификаторКлиента);
КонецПроцедуры

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

// Сохраняет путь к рабочему каталогу пользователя в настройках.
//
// Параметры:
//  ИмяКаталога - Строка - имя каталога.
//  Пользователь - СправочникСсылка.Пользователи - пользователь, для которого будет установлен рабочий каталог.
//               - Неопределено - рабочий каталог будет установлен для текущего пользователя.
//
Процедура УстановитьРабочийКаталогПользователя(ИмяКаталога, Пользователь = Неопределено) Экспорт

	ИмяПользователя = Неопределено;

	УстановитьПривилегированныйРежим(Истина);
	Если Пользователь <> Неопределено Тогда
		ИдентификаторПользователяИБ = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Пользователь,
			"ИдентификаторПользователяИБ");
		СвойстваПользователяИБ = Пользователи.СвойстваПользователяИБ(ИдентификаторПользователяИБ);
		ИмяПользователя = ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(СвойстваПользователяИБ, "Имя");
	КонецЕсли;

	ОбщегоНазначенияВызовСервера.ХранилищеОбщихНастроекСохранить(
		"ЛокальныйКэшФайлов", "ПутьКЛокальномуКэшуФайлов", ИмяКаталога,, ИмяПользователя, Истина);

КонецПроцедуры

Функция ЭтоСправочникФайлы(ВладелецФайлов) Экспорт

	Возврат РаботаСФайламиСлужебный.ИмяСправочникаХраненияФайлов(ВладелецФайлов) = "Файлы";

КонецФункции

Функция ИмяСправочникаХраненияФайлов(ВладелецФайлов) Экспорт

	Возврат РаботаСФайламиСлужебный.ИмяСправочникаХраненияФайлов(ВладелецФайлов);

КонецФункции

// Создает файл в ИБ.
//
// Параметры:
//   Владелец       - СправочникСсылка.ПапкиФайлов
//                  - ЛюбаяСсылка - будет установлен в реквизит ВладелецФайла у
//                    созданного файла.
//   СведенияОФайле - см. РаботаСФайламиКлиентСервер.СведенияОФайле
//
// Возвращаемое значение:
//    СправочникСсылка.Файлы - созданный файл.
//
Функция СоздатьФайл(Знач Владелец, Знач СведенияОФайле)

	МенеджерСправочникаФайлов = Справочники[СведенияОФайле.ИмяСправочникаХранилищаФайлов]; // СправочникМенеджер

	Файл = МенеджерСправочникаФайлов.СоздатьЭлемент(); // ОпределяемыйТип.ПрисоединенныйФайлОбъект
	Файл.ВладелецФайла = Владелец;
	Файл.Наименование = СведенияОФайле.ИмяБезРасширения;
	Файл.Автор = ?(СведенияОФайле.Автор <> Неопределено, СведенияОФайле.Автор,
		Пользователи.АвторизованныйПользователь());
	Файл.Изменил = Файл.Автор;
	Файл.ДатаСоздания = ТекущаяДатаСеанса();
	Файл.Описание = СведенияОФайле.Комментарий;
	Файл.ИндексКартинки = РаботаСФайламиСлужебныйКлиентСервер.ПолучитьИндексПиктограммыФайла(Неопределено);
	Файл.ХранитьВерсии = СведенияОФайле.ХранитьВерсии;
	Файл.Расширение = СведенияОФайле.РасширениеБезТочки;
	Файл.Размер = СведенияОФайле.Размер;
	Файл.ДатаМодификацииУниверсальная = СведенияОФайле.ВремяИзмененияУниверсальное;

	ИспользованиеПолнотекстовогоПоиска = Метаданные.СвойстваОбъектов.ИспользованиеПолнотекстовогоПоиска.Использовать;
	Если Метаданные.Справочники[СведенияОФайле.ИмяСправочникаХранилищаФайлов].ПолнотекстовыйПоиск
		= ИспользованиеПолнотекстовогоПоиска Тогда

		Если ТипЗнч(СведенияОФайле.АдресВременногоХранилищаТекста) = Тип("ХранилищеЗначения") Тогда
			// При создании Файла из шаблона хранилище значения копируется напрямую.
			Файл.ТекстХранилище = СведенияОФайле.АдресВременногоХранилищаТекста;
		ИначеЕсли Не ПустаяСтрока(СведенияОФайле.АдресВременногоХранилищаТекста) Тогда
			РезультатИзвлеченияТекста = РаботаСФайламиСлужебный.ИзвлечьТекст(
				СведенияОФайле.АдресВременногоХранилищаТекста);
			Файл.ТекстХранилище = РезультатИзвлеченияТекста.ТекстХранилище;
			Файл.СтатусИзвлеченияТекста = РезультатИзвлеченияТекста.СтатусИзвлеченияТекста;
		КонецЕсли;

	Иначе
		Файл.ТекстХранилище = Новый ХранилищеЗначения("");
		Файл.СтатусИзвлеченияТекста = Перечисления.СтатусыИзвлеченияТекстаФайлов.НеИзвлечен;
	КонецЕсли;

	Файл.Заполнить(Неопределено);
	Файл.Записать();
	Возврат Файл.Ссылка;

КонецФункции

// Обновляет или создает версию Файла и возвращает ссылку на обновленную версию (или Ложь, если файл бинарно не
// изменен).
//
// Параметры:
//   ФайлСсылка     - СправочникСсылка.Файлы        - файл, для которого создается новая версия.
//   СведенияОФайле - см. РаботаСФайламиКлиентСервер.СведенияОФайле
//   ВерсияСсылка   - СправочникСсылка.ВерсииФайлов - версия файла, которую надо обновить.
//   УникальныйИдентификаторФормы                   - УникальныйИдентификатор - уникальный идентификатор формы, 
//                                                    в контексте которой выполняется операция.
//
// Возвращаемое значение:
//   СправочникСсылка.ВерсииФайлов - созданная или измененная версия; Неопределено, если файл бинарно не был изменен.
//
Функция ОбновитьОбъектФайла(ФайлСсылка, СведенияОФайле, ВерсияСсылка = Неопределено,
	УникальныйИдентификаторФормы = Неопределено, Пользователь = Неопределено)

	ЕстьПравоСохранения = ПравоДоступа("СохранениеДанныхПользователя", Метаданные);
	ЕстьПраваНаОбъект = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(ФайлСсылка, "Ссылка", Истина);
	Если ЕстьПраваНаОбъект = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;

	УстановитьПривилегированныйРежим(Истина);

	ВремяИзмененияУниверсальное = СведенияОФайле.ВремяИзмененияУниверсальное;
	Если Не ЗначениеЗаполнено(ВремяИзмененияУниверсальное) Или ВремяИзмененияУниверсальное > ТекущаяУниверсальнаяДата() Тогда
		ВремяИзмененияУниверсальное = ТекущаяУниверсальнаяДата();
	КонецЕсли;

	ВремяИзменения = СведенияОФайле.ВремяИзменения;
	Если Не ЗначениеЗаполнено(ВремяИзменения) Или УниверсальноеВремя(ВремяИзменения) > ВремяИзмененияУниверсальное Тогда
		ВремяИзменения = ТекущаяДатаСеанса();
	КонецЕсли;

	РаботаСФайламиСлужебный.ПроверитьРасширениеФайлаДляЗагрузки(СведенияОФайле.РасширениеБезТочки);

	ДвоичныеДанные = Неопределено;
	МетаданныеСправочника = Метаданные.НайтиПоТипу(ТипЗнч(ФайлСсылка));
	СправочникПоддерживаетВозможностьХранитьВерсии = ОбщегоНазначения.ЕстьРеквизитОбъекта("ТекущаяВерсия",
		МетаданныеСправочника);

	ВерсияСсылкаДляСравненияРазмера = ВерсияСсылка;
	Если ВерсияСсылка <> Неопределено Тогда
		ВерсияСсылкаДляСравненияРазмера = ВерсияСсылка;
	ИначеЕсли СправочникПоддерживаетВозможностьХранитьВерсии И ЗначениеЗаполнено(ФайлСсылка.ТекущаяВерсия) Тогда
		ВерсияСсылкаДляСравненияРазмера = ФайлСсылка.ТекущаяВерсия;
	Иначе
		ВерсияСсылкаДляСравненияРазмера = ФайлСсылка;
	КонецЕсли;

	КодировкаПредВерсии = РегистрыСведений.КодировкиФайлов.КодировкаВерсииФайла(ВерсияСсылкаДляСравненияРазмера);

	СтруктураРеквизитов = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(ВерсияСсылкаДляСравненияРазмера,
		"Размер, ТипХраненияФайла");

	ХранилищеФайла = Неопределено;
	Если СведенияОФайле.Размер = СтруктураРеквизитов.Размер Тогда

		Если СтруктураРеквизитов.ТипХраненияФайла = Перечисления.ТипыХраненияФайлов.ВТомахНаДиске Тогда
			ДвоичныеДанныеПредыдущейВерсии = РаботаСФайламиВТомахСлужебный.ДанныеФайла(ВерсияСсылкаДляСравненияРазмера,
				Ложь);
		Иначе
			ХранилищеФайла = РаботаСФайлами.ХранилищеФайлаИзИнформационнойБазы(ВерсияСсылкаДляСравненияРазмера);
			ДвоичныеДанныеПредыдущейВерсии = ХранилищеФайла.Получить();
		КонецЕсли;

		ДвоичныеДанные = РаботаСФайламиСлужебный.ДвоичныеДанныеИзСведенийОФайле(СведенияОФайле);
		Если ДвоичныеДанныеПредыдущейВерсии = ДвоичныеДанные Тогда
			Возврат Неопределено; // Файл бинарно не изменен - вернем Ложь.
		КонецЕсли;

	КонецЕсли;

	СсылкаНаВерсию = ?(ВерсияСсылка = Неопределено, ФайлСсылка, ВерсияСсылка);

	Блокировка = Новый БлокировкаДанных;
	ЭлементБлокировки = Блокировка.Добавить(СсылкаНаВерсию.Метаданные().ПолноеИмя());
	ЭлементБлокировки.УстановитьЗначение("Ссылка", СсылкаНаВерсию);

	Расширение = ОбщегоНазначенияКлиентСервер.РасширениеБезТочки(СведенияОФайле.РасширениеБезТочки);
	ТипХраненияФайла = РаботаСФайламиСлужебный.ТипХраненияФайла(СведенияОФайле.Размер, Расширение);
	МенеджерФайла = РаботаСФайламиСлужебный.МенеджерФайловПоТипу(ТипХраненияФайла);
	Контекст = РаботаСФайламиСлужебный.КонтекстОбновленияФайла(СсылкаНаВерсию,
		СведенияОФайле.АдресВременногоХранилищаФайла,, ТипХраненияФайла);
	МенеджерФайла.ПередОбновлениемДанныхФайла(Контекст);

	НачатьТранзакцию();
	Попытка

		Блокировка.Заблокировать();

		Версия = СсылкаНаВерсию.ПолучитьОбъект();
		ЗаблокироватьДанныеДляРедактирования(СсылкаНаВерсию,, УникальныйИдентификаторФормы);

		Версия.ТипХраненияФайла = ТипХраненияФайла;
		Если Версия.ТипХраненияФайла = Перечисления.ТипыХраненияФайлов.ВТомахНаДиске Тогда
			СвойстваВерсии = РаботаСФайламиВТомахСлужебный.СвойстваФайлаВТоме();
			ЗаполнитьЗначенияСвойств(СвойстваВерсии, Версия);
		КонецЕсли;

		Если Пользователь = Неопределено Тогда
			Версия.Изменил = Пользователи.АвторизованныйПользователь();
		Иначе
			Версия.Изменил = Пользователь;
		КонецЕсли;
		Версия.ДатаМодификацииУниверсальная = ВремяИзмененияУниверсальное;
		Версия.Размер                       = СведенияОФайле.Размер;
		Версия.Наименование                 = СведенияОФайле.ИмяБезРасширения;
		Версия.Описание                     = СведенияОФайле.Комментарий;
		Версия.Расширение                   = Расширение;

		Если ДвоичныеДанные = Неопределено Тогда
			ДвоичныеДанные = РаботаСФайламиСлужебный.ДвоичныеДанныеИзСведенийОФайле(СведенияОФайле);
		КонецЕсли;

		Если ТипХраненияФайла = Перечисления.ТипыХраненияФайлов.ВИнформационнойБазе Тогда

			ХранилищеФайла = Новый ХранилищеЗначения(ДвоичныеДанные);

			Если Версия.Размер = 0 Тогда
				ДвоичныеДанныеФайла = ХранилищеФайла.Получить(); // ДвоичныеДанные
				Версия.Размер = ДвоичныеДанныеФайла.Размер();

				РаботаСФайламиСлужебный.ПроверитьРазмерФайлаДляЗагрузки(Версия);
			КонецЕсли;
			
			// очистим поля
			Версия.ПутьКФайлу = "";
			Версия.Том = Справочники.ТомаХраненияФайлов.ПустаяСсылка();

		Иначе // хранение в томе

			Если Версия.Размер = 0 Тогда
				Версия.Размер = ДвоичныеДанные.Размер();
				РаботаСФайламиСлужебный.ПроверитьРазмерФайлаДляЗагрузки(Версия);
			КонецЕсли;
			Версия.ФайлХранилище = Новый ХранилищеЗначения(Неопределено);
			РаботаСФайламиВТомахСлужебный.ЗаполнитьСведенияОФайле(Версия, ДвоичныеДанные);
		КонецЕсли;

		ИспользованиеПолнотекстовогоПоиска = Метаданные.СвойстваОбъектов.ИспользованиеПолнотекстовогоПоиска.Использовать;
		Если МетаданныеСправочника.ПолнотекстовыйПоиск = ИспользованиеПолнотекстовогоПоиска Тогда

			Если СведенияОФайле.АдресВременногоХранилищаТекста <> Неопределено Тогда
				Если РаботаСФайламиСлужебный.ИзвлекатьТекстыФайловНаСервере() Тогда
					Версия.СтатусИзвлеченияТекста = Перечисления.СтатусыИзвлеченияТекстаФайлов.НеИзвлечен;
				Иначе
					РезультатИзвлеченияТекста = РаботаСФайламиСлужебный.ИзвлечьТекст(
						СведенияОФайле.АдресВременногоХранилищаТекста);
					Версия.ТекстХранилище = РезультатИзвлеченияТекста.ТекстХранилище;
					Версия.СтатусИзвлеченияТекста = РезультатИзвлеченияТекста.СтатусИзвлеченияТекста;
				КонецЕсли;
			Иначе
				Версия.СтатусИзвлеченияТекста = Перечисления.СтатусыИзвлеченияТекстаФайлов.НеИзвлечен;
			КонецЕсли;

			Если СведенияОФайле.НовыйСтатусИзвлеченияТекста <> Неопределено Тогда
				Версия.СтатусИзвлеченияТекста = СведенияОФайле.НовыйСтатусИзвлеченияТекста;
			КонецЕсли;

		Иначе
			Версия.СтатусИзвлеченияТекста = Перечисления.СтатусыИзвлеченияТекстаФайлов.НеИзвлечен;
		КонецЕсли;

		Если Версия.Размер = 0 Тогда
			Если ТипХраненияФайла = Перечисления.ТипыХраненияФайлов.ВИнформационнойБазе Тогда
				ДвоичныеДанныеФайла = ХранилищеФайла.Получить(); // ДвоичныеДанные
				Версия.Размер = ДвоичныеДанныеФайла.Размер();
			КонецЕсли;
		КонецЕсли;

		Версия.Заполнить(Неопределено);

		МенеджерФайла.ПередЗаписьюДанныхФайла(Контекст, Версия);
		Версия.Записать();
		МенеджерФайла.ПриОбновленииДанныхФайла(Контекст, Версия.Ссылка);

		РегистрыСведений.КодировкиФайлов.ЗаписатьКодировкуВерсииФайла(Версия.Ссылка, КодировкаПредВерсии);
		Если СведенияОФайле.ХранитьВерсии Тогда
			РаботаСФайламиСлужебный.ОбновитьВерсиюВФайле(ФайлСсылка, Версия.Ссылка,
				СведенияОФайле.АдресВременногоХранилищаТекста, УникальныйИдентификаторФормы);
		Иначе
			РаботаСФайламиСлужебный.ОбновитьТекстВФайле(ФайлСсылка, СведенияОФайле.АдресВременногоХранилищаТекста,
				УникальныйИдентификаторФормы);
		КонецЕсли;

		РазблокироватьДанныеДляРедактирования(СсылкаНаВерсию, УникальныйИдентификаторФормы);
		ЗафиксироватьТранзакцию();

	Исключение
		ОтменитьТранзакцию();
		РазблокироватьДанныеДляРедактирования(СсылкаНаВерсию, УникальныйИдентификаторФормы);
		МенеджерФайла.ПослеОбновленияДанныхФайла(Контекст, Ложь);
		ВызватьИсключение;
	КонецПопытки;

	МенеджерФайла.ПослеОбновленияДанныхФайла(Контекст, Истина);

	Если ЕстьПравоСохранения Тогда
		НавигационнаяСсылкаФайла = ПолучитьНавигационнуюСсылку(ФайлСсылка);
		ИсторияРаботыПользователя.Добавить(НавигационнаяСсылкаФайла);
	КонецЕсли;

	Возврат Версия.Ссылка;

КонецФункции

// Обновляет или создает версию файла и снимает блокировку. 
// 
// Выбрасывает исключение.
//
// Параметры:
//   ДанныеФайла                  - Структура - структура с данными файла.
//   СведенияОФайле               - см. РаботаСФайламиКлиентСервер.СведенияОФайле
//   НеМенятьЗаписьВРабочемКаталоге - Булево  - не менять запись в регистре сведений ФайлыВРабочемКаталоге.
//   ПолныйПутьКФайлу             - Строка    - указывается, если НеМенятьЗаписьВРабочемКаталоге = Ложь.
//   РабочийКаталогПользователя   - Строка    - указывается, если НеМенятьЗаписьВРабочемКаталоге = Ложь.
//   УникальныйИдентификаторФормы - УникальныйИдентификатор - уникальный идентификатор формы.
//
// Возвращаемое значение:
//   Булево - Истина, если создание версии выполнено (и файл бинарно изменен).
//
Функция СохранитьИзмененияИОсвободитьФайл(ДанныеФайла, СведенияОФайле, НеМенятьЗаписьВРабочемКаталоге,
	ПолныйПутьКФайлу, РабочийКаталогПользователя, УникальныйИдентификаторФормы = Неопределено) Экспорт

	ПараметрыДанныхФайла = РаботаСФайламиКлиентСервер.ПараметрыДанныхФайла();
	ПараметрыДанныхФайла.ПолучатьСсылкуНаДвоичныеДанные = Ложь;

	ДанныеФайлаТекущие = ДанныеФайла(ДанныеФайла.Ссылка,, ПараметрыДанныхФайла);
	Если Не ДанныеФайлаТекущие.ФайлРедактируетТекущийПользователь И Не ФайлСинхронизируетсяОблачнымСервисом(
		ДанныеФайла.Ссылка) Тогда
		ВызватьИсключение НСтр("ru = 'Файл не занят текущим пользователем'");
	КонецЕсли;

	ПредыдущаяВерсия = ДанныеФайла.ТекущаяВерсия;
	СведенияОФайле.Зашифрован = ДанныеФайла.Зашифрован;
	СведенияОФайле.Кодировка  = ДанныеФайла.Кодировка;

	Если ТипЗнч(ДанныеФайла.Ссылка) = Тип("СправочникСсылка.Файлы") Тогда
		НоваяВерсия = РаботаСФайламиСлужебный.ОбновитьВерсиюФайла(ДанныеФайла.Ссылка, СведенияОФайле,,
			УникальныйИдентификаторФормы);
	Иначе
		НоваяВерсия = ОбновитьОбъектФайла(ДанныеФайла.Ссылка, СведенияОФайле,, УникальныйИдентификаторФормы);
	КонецЕсли;

	ОсвободитьФайл(ДанныеФайла, УникальныйИдентификаторФормы);

	Если НоваяВерсия = Неопределено Тогда
		Возврат Ложь;
	КонецЕсли;

	ДанныеФайла.ТекущаяВерсия = НоваяВерсия;

	Если Не ОбщегоНазначения.ЭтоВебКлиент() И Не НеМенятьЗаписьВРабочемКаталоге Тогда
		УдалитьВерсиюИЗанестиИнформациюФайлаВРегистр(ПредыдущаяВерсия, НоваяВерсия, ПолныйПутьКФайлу,
			РабочийКаталогПользователя, ДанныеФайла.РабочийКаталогВладельца <> "");
	КонецЕсли;

	Возврат Истина;

КонецФункции

// Получает данные файла, затем обновляет или создает версию Файла и снимает блокировку.
// Нужно для случаев, когда на клиенте нет ДанныеФайла (из соображений экономии вызовов клиент-сервер).
//
// Параметры:
//   ФайлСсылка       - СправочникСсылка.Файлы - файл, в котором обновляется версия.
//   СведенияОФайле   - см. РаботаСФайламиКлиентСервер.СведенияОФайле
//   ПолныйПутьКФайлу             - Строка
//   РабочийКаталогПользователя   - Строка
//   УникальныйИдентификаторФормы - УникальныйИдентификатор - уникальный идентификатор формы.
//
// Возвращаемое значение:
//   Структура:
//     * Успешно     - Булево    - Истина, если создание версии выполнено (и файл бинарно изменен).
//     * ДанныеФайла - Структура - структура с данными файла.
//
Функция СохранитьИзмененияИОсвободитьФайлПоСсылке(ФайлСсылка, СведенияОФайле, ПолныйПутьКФайлу,
	РабочийКаталогПользователя, УникальныйИдентификаторФормы = Неопределено) Экспорт

	ПараметрыДанныхФайла = РаботаСФайламиКлиентСервер.ПараметрыДанныхФайла();
	ПараметрыДанныхФайла.ПолучатьСсылкуНаДвоичныеДанные = Ложь;

	ДанныеФайла = ДанныеФайла(ФайлСсылка,, ПараметрыДанныхФайла);
	ВерсияСоздана = СохранитьИзмененияИОсвободитьФайл(ДанныеФайла, СведенияОФайле, Ложь, ПолныйПутьКФайлу,
		РабочийКаталогПользователя, УникальныйИдентификаторФормы);
	Возврат Новый Структура("Успешно,ДанныеФайла", ВерсияСоздана, ДанныеФайла);

КонецФункции

// Предназначена для записи изменений файла без его освобождения.
//
// Параметры:
//   ФайлСсылка                  - ОпределяемыйТип.ПрисоединенныйФайл - присоединенный файл.
//   СведенияОФайле               - см. РаботаСФайламиКлиентСервер.СведенияОФайле
//   НеМенятьЗаписьВРабочемКаталоге - Булево  - не менять запись в регистре сведений ФайлыВРабочемКаталоге.
//   ОтносительныйПутьКФайлу      - Строка    - относительный путь без пути рабочего каталога, например
//                                              "А1/Приказ.doc"; указывается, если НеМенятьЗаписьВРабочемКаталоге =
//                                              Ложь.
//   ПолныйПутьКФайлу             - Строка    - путь на клиенте в рабочем каталоге; указывается, если
//                                              НеМенятьЗаписьВРабочемКаталоге = Ложь.
//   ВРабочемКаталогеВладельца    - Булево    - файл находится в рабочем каталоге владельца.
//   УникальныйИдентификаторФормы - УникальныйИдентификатор - уникальный идентификатор формы.
//
// Возвращаемое значение:
//   Булево  - Истина, если создание версии выполнено (и файл бинарно изменен).
//
Функция СохранитьИзмененияФайла(ФайлСсылка, СведенияОФайле, НеМенятьЗаписьВРабочемКаталоге, ОтносительныйПутьКФайлу,
	ПолныйПутьКФайлу, ВРабочемКаталогеВладельца, УникальныйИдентификаторФормы = Неопределено) Экспорт

	ПараметрыДанныхФайла = РаботаСФайламиКлиентСервер.ПараметрыДанныхФайла();
	ПараметрыДанныхФайла.ПолучатьСсылкуНаДвоичныеДанные = Ложь;
	ДанныеФайлаТекущие = ДанныеФайла(ФайлСсылка,, ПараметрыДанныхФайла);
	Если Не ДанныеФайлаТекущие.ФайлРедактируетТекущийПользователь И Не ФайлСинхронизируетсяОблачнымСервисом(ФайлСсылка) Тогда
		ВызватьИсключение НСтр("ru = 'Файл не занят текущим пользователем'");
	КонецЕсли;

	СтараяВерсия = ?(СведенияОФайле.ХранитьВерсии, ФайлСсылка.ТекущаяВерсия, ФайлСсылка);
	Если СведенияОФайле.Зашифрован = Неопределено Тогда
		СведенияОФайле.Зашифрован = ДанныеФайлаТекущие.Зашифрован;
	КонецЕсли;

	Если СведенияОФайле.Кодировка = Неопределено Тогда
		СведенияОФайле.Кодировка = РаботаСФайламиСлужебныйКлиентСервер.ОпределитьКодировкуДвоичныхДанных(
			СведенияОФайле.АдресВременногоХранилищаФайла, СведенияОФайле.РасширениеБезТочки);
	КонецЕсли;

	Если ТипЗнч(ФайлСсылка.Ссылка) = Тип("СправочникСсылка.Файлы") Тогда
		НоваяВерсия = РаботаСФайламиСлужебный.ОбновитьВерсиюФайла(ФайлСсылка.Ссылка, СведенияОФайле,,
			УникальныйИдентификаторФормы, СведенияОФайле.НоваяВерсияАвтор);
	Иначе
		НоваяВерсия = ОбновитьОбъектФайла(ФайлСсылка.Ссылка, СведенияОФайле,, УникальныйИдентификаторФормы);
	КонецЕсли;

	Если НоваяВерсия = Неопределено Тогда
		Возврат Ложь;
	КонецЕсли;

	Если СведенияОФайле.ХранитьВерсии Тогда

		Если Не ОбщегоНазначения.ЭтоВебКлиент() И Не НеМенятьЗаписьВРабочемКаталоге Тогда
			УдалитьИзРегистра(СтараяВерсия);
			ЗаписатьПолноеИмяФайлаВРегистр(НоваяВерсия, ОтносительныйПутьКФайлу, Ложь, ВРабочемКаталогеВладельца);
		КонецЕсли;

	КонецЕсли;

	Возврат Истина;

КонецФункции

// Создает новый файл по аналогии с указанным и возвращает ссылку на него.
// 
// Параметры:
//  ИсходныйФайл  - СправочникСсылка.Файлы - существующий файл.
//  ВладелецНовогоФайла - ОпределяемыйТип.ВладелецФайлов - владелец файла.
//
// Возвращаемое значение:
//   СправочникСсылка.Файлы - новый файл.
//
Функция СкопироватьФайл(ИсходныйФайл, ВладелецНовогоФайла)

	Если ИсходныйФайл = Неопределено Или ИсходныйФайл.Пустая() Тогда
		Возврат Неопределено;
	КонецЕсли;

	МенеджерОбъекта = ОбщегоНазначения.МенеджерОбъектаПоСсылке(ИсходныйФайл);
	НовыйФайл = ИсходныйФайл.Скопировать();
	КопияФайлаСсылка = МенеджерОбъекта.ПолучитьСсылку();
	НовыйФайл.УстановитьСсылкуНового(КопияФайлаСсылка);
	НовыйФайл.ВладелецФайла = ВладелецНовогоФайла;
	НовыйФайл.Редактирует = Справочники.Пользователи.ПустаяСсылка();

	НовыйФайл.ТекстХранилище = Новый ХранилищеЗначения(ИсходныйФайл.ТекстХранилище.Получить());
	НовыйФайл.ФайлХранилище  = Новый ХранилищеЗначения(ИсходныйФайл.ФайлХранилище.Получить());

	ДвоичныеДанные = РаботаСФайлами.ДвоичныеДанныеФайла(ИсходныйФайл);
	ДвоичныеДанныеВХранилищеЗначения = Новый ХранилищеЗначения(ДвоичныеДанные);

	ТипХраненияФайла = РаботаСФайламиСлужебный.ТипХраненияФайла(НовыйФайл.Размер, НовыйФайл.Расширение);
	Если ТипХраненияФайла = Перечисления.ТипыХраненияФайлов.ВИнформационнойБазе Тогда
		НовыйФайл.ТипХраненияФайла = РаботаСФайламиСлужебный.ТипХраненияФайлов();
		ЗаписатьФайлВИнформационнуюБазу(КопияФайлаСсылка, ДвоичныеДанныеВХранилищеЗначения);
	Иначе

		НовыйФайл.Том = Неопределено;
		НовыйФайл.ПутьКФайлу = Неопределено;
		НовыйФайл.ТипХраненияФайла = Неопределено;

		РаботаСФайламиВТомахСлужебный.ДобавитьФайл(НовыйФайл, ДвоичныеДанные);

	КонецЕсли;

	НовыйФайл.Записать();

	Если НовыйФайл.ХранитьВерсии Тогда

		РеквизитыТекущейВерсии = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(НовыйФайл.ТекущаяВерсия,
			"Размер,Расширение,ТекстХранилище");

		СведенияОФайле = РаботаСФайламиКлиентСервер.СведенияОФайле("ФайлСВерсией");
		СведенияОФайле.ИмяБезРасширения = НовыйФайл.Наименование;
		СведенияОФайле.Размер = РеквизитыТекущейВерсии.Размер;
		СведенияОФайле.РасширениеБезТочки = РеквизитыТекущейВерсии.Расширение;
		СведенияОФайле.АдресВременногоХранилищаФайла = ДвоичныеДанныеВХранилищеЗначения;
		СведенияОФайле.АдресВременногоХранилищаТекста = РеквизитыТекущейВерсии.ТекстХранилище;
		СведенияОФайле.СсылкаНаВерсиюИсточник = НовыйФайл.ТекущаяВерсия;
		СведенияОФайле.Зашифрован = НовыйФайл.Зашифрован;
		Версия = РаботаСФайламиСлужебный.СоздатьВерсию(НовыйФайл.Ссылка, СведенияОФайле);
		РаботаСФайламиСлужебный.ОбновитьВерсиюВФайле(НовыйФайл.Ссылка, Версия, РеквизитыТекущейВерсии.ТекстХранилище);

	КонецЕсли;

	Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ЭлектроннаяПодпись") Тогда

		МодульЭлектроннаяПодписьСлужебный = ОбщегоНазначения.ОбщийМодуль("ЭлектроннаяПодписьСлужебный");
		ДоступнаЭлектроннаяПодпись = МодульЭлектроннаяПодписьСлужебный.ДоступнаЭлектроннаяПодпись(ТипЗнч(ИсходныйФайл));
		Если ДоступнаЭлектроннаяПодпись Тогда

			МодульЭлектроннаяПодпись = ОбщегоНазначения.ОбщийМодуль("ЭлектроннаяПодпись");

			Если ИсходныйФайл.ПодписанЭП Тогда

				НовыйФайл.Прочитать();
				НовыйФайл.ПодписанЭП = Истина;
				НовыйФайл.Записать();

				ЭлектронныеПодписиИсходногоФайла = МодульЭлектроннаяПодпись.УстановленныеПодписи(ИсходныйФайл);
				Для Каждого ЭП Из ЭлектронныеПодписиИсходногоФайла Цикл
					МенеджерЗаписи = РегистрыСведений["ЭлектронныеПодписи"].СоздатьМенеджерЗаписи(); // РегистрСведенийМенеджерЗаписи.ЭлектронныеПодписи
					МенеджерЗаписи.ПодписанныйОбъект = НовыйФайл;
					ЗаполнитьЗначенияСвойств(МенеджерЗаписи, ЭП);
					МенеджерЗаписи.Записать(Истина);
				КонецЦикла;

			КонецЕсли;

			Если ИсходныйФайл.Зашифрован Тогда

				НовыйФайл.Прочитать();
				НовыйФайл.Зашифрован = Истина;

				ЭлектронныеПодписиИсходногоФайла = МодульЭлектроннаяПодпись.СертификатыШифрования(ИсходныйФайл);
				Для Каждого Сертификат Из ЭлектронныеПодписиИсходногоФайла Цикл
					МенеджерЗаписи = РегистрыСведений["СертификатыШифрования"].СоздатьМенеджерЗаписи(); // РегистрСведенийМенеджерЗаписи.СертификатыШифрования
					МенеджерЗаписи.ЗашифрованныйОбъект = НовыйФайл;
					ЗаполнитьЗначенияСвойств(МенеджерЗаписи, Сертификат);
					МенеджерЗаписи.Записать(Истина);
				КонецЦикла;
				// Чтобы прошла запись ранее подписанного объекта.
				НовыйФайл.ДополнительныеСвойства.Вставить("ЗаписьПодписанногоОбъекта", Истина);
				НовыйФайл.Записать();

			КонецЕсли;

		КонецЕсли;

	КонецЕсли;

	РаботаСФайламиПереопределяемый.ЗаполнитьРеквизитыФайлаИзИсходногоФайла(НовыйФайл, ИсходныйФайл);

	Возврат НовыйФайл;

КонецФункции

// Переносит Файл в другую папку.
//
// Параметры:
//  ДанныеФайла - см. ДанныеФайла
//  Папка - СправочникСсылка.ПапкиФайлов - ссылка на папку, куда нужно переместить файл.
//
Процедура ПеренестиФайл(ДанныеФайла, Папка)

	НачатьТранзакцию();
	Попытка
		БлокировкаДанных = Новый БлокировкаДанных;
		ЭлементБлокировкиДанных = БлокировкаДанных.Добавить(Метаданные.НайтиПоТипу(ТипЗнч(
			ДанныеФайла.Ссылка)).ПолноеИмя());
		ЭлементБлокировкиДанных.УстановитьЗначение("Ссылка", ДанныеФайла.Ссылка);
		БлокировкаДанных.Заблокировать();
		ФайлОбъект = ДанныеФайла.Ссылка.ПолучитьОбъект();
		ФайлОбъект.Заблокировать();
		ФайлОбъект.ВладелецФайла = Папка;
		ФайлОбъект.Записать();
		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		ВызватьИсключение;
	КонецПопытки;

КонецПроцедуры

// Переносит Файлы в другую папку.
//
// Параметры:
//   ОбъектыСсылка - Массив - массив ссылок на файлы.
//   Папка - СправочникСсылка.ПапкиФайлов - ссылка на папку, куда нужно переместить файлы.
//
// Возвращаемое значение:
//    Массив из см. РаботаСФайламиСлужебныйВызовСервера.ДанныеФайла
//
Функция ПеренестиФайлы(ОбъектыСсылка, Папка) Экспорт

	ДанныеФайлов = Новый Массив;

	ПараметрыДанныхФайла = РаботаСФайламиКлиентСервер.ПараметрыДанныхФайла();
	ПараметрыДанныхФайла.ПолучатьСсылкуНаДвоичныеДанные = Ложь;

	Для Каждого ФайлСсылка Из ОбъектыСсылка Цикл
		ПеренестиФайл(ФайлСсылка, Папка);
		ДанныеФайла = ДанныеФайла(ФайлСсылка,, ПараметрыДанныхФайла);
		ДанныеФайлов.Добавить(ДанныеФайла);
	КонецЦикла;

	Возврат ДанныеФайлов;

КонецФункции

// Получает РедактируетТекущийПользователь - в привилегированном режиме.
// Параметры:
//  ВерсияСсылка  - СправочникСсылка.ВерсииФайлов - версия файла.
//
// Возвращаемое значение:
//   Булево - Истина, если файл редактирует текущий пользователь.
//
Функция ПолучитьРедактируетТекущийПользователь(ВерсияСсылка) Экспорт

	УстановитьПривилегированныйРежим(Истина);

	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ
	|	Файлы.Редактирует КАК Редактирует
	|ИЗ
	|	Справочник.Файлы КАК Файлы
	|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.ВерсииФайлов КАК ВерсииФайлов
	|		ПО (ИСТИНА)
	|ГДЕ
	|	ВерсииФайлов.Ссылка = &Версия
	|	И Файлы.Ссылка = ВерсииФайлов.Владелец";

	Запрос.Параметры.Вставить("Версия", ВерсияСсылка);

	Выборка = Запрос.Выполнить().Выбрать();
	Если Выборка.Следующий() Тогда
		РедактируетТекущийПользователь = (Выборка.Редактирует = Пользователи.АвторизованныйПользователь());
		Возврат РедактируетТекущийПользователь;
	КонецЕсли;

	Возврат Ложь;

КонецФункции

// Получает данные файла и делает заем (checkout) - для экономии вызовов 
// клиент сервер поместили ПолучитьДанныеФайла и ЗанятьФайл в одну функцию.
// Параметры:
//  ФайлСсылка  - СправочникСсылка.Файлы - файл.
//  ДанныеФайла  - Структура - структура с данными файла.
//  СтрокаОшибки - Строка - в которой возвращается причина ошибки в случае неуспеха (скажем "Файл занят другим
//                 пользователем").
//  УникальныйИдентификатор - уникальный идентификатор формы.
//
// Возвращаемое значение:
//   Булево  - успешно ли выполнена операция.
//
Функция ПолучитьДанныеФайлаИЗанятьФайл(ФайлСсылка, ДанныеФайла, СтрокаОшибки, УникальныйИдентификатор = Неопределено) Экспорт

	ДанныеФайла = ДанныеФайла(ФайлСсылка);

	СтрокаОшибки = "";
	Если Не РаботаСФайламиКлиентСервер.МожноЛиЗанятьФайл(ДанныеФайла, СтрокаОшибки) Тогда
		Возврат Ложь;
	КонецЕсли;

	Если Не ЗначениеЗаполнено(ДанныеФайла.Редактирует) Тогда

		ПараметрыЗанятияФайла = РаботаСФайламиСлужебныйКлиентСервер.ПараметрыЗанятияФайла();
		ПараметрыЗанятияФайла.УникальныйИдентификатор = УникальныйИдентификатор;

		СтрокаОшибки = "";
		Если Не ЗанятьФайл(ДанныеФайла, СтрокаОшибки, ПараметрыЗанятияФайла) Тогда
			Возврат Ложь;
		КонецЕсли;
	КонецЕсли;

	Возврат Истина;

КонецФункции

// Получает ДанныеФайла для файлов и помещает в МассивДанныхФайла.
//
// Параметры:
//  МассивФайлов - Массив из ОпределяемыйТип.ПрисоединенныйФайл
//  МассивДанныхФайла - Массив - структуры с данными файлов.
//
Процедура ПолучитьДанныеДляМассиваФайлов(Знач МассивФайлов, МассивДанныхФайла) Экспорт

	Для Каждого Файл Из МассивФайлов Цикл
		ДанныеФайла = ДанныеФайла(Файл);
		МассивДанныхФайла.Добавить(ДанныеФайла);
	КонецЦикла;

КонецПроцедуры

// Занимает файл на редактирование и возвращает данные файла для открытия в редакторе.
// 
// Параметры:
//  ФайлСсылка  - СправочникСсылка.Файлы
//  УникальныйИдентификатор - уникальный идентификатор формы.
//  РабочийКаталогВладельца - Строка - рабочий каталог владельца файла.
//  ВерсияСсылка - СправочникСсылка.ВерсииФайлов
//
// Возвращаемое значение:
//   Структура:
//    * ДанныеПолучены - Булево  - Истина, если операция успешна.
//    * ДанныеФайла    - Структура
//    * ТекстСообщения - Строка - описание причины в случае неуспеха, например, "Файл занят другим пользователем".
//    * ФайлУжеРедактируетТекущийПользователь - Булево - Истина, если файл уже открыт на редактирование ранее.
///
Функция ЗанятьФайлДляРедактирования(ФайлСсылка, УникальныйИдентификатор = Неопределено,
	РабочийКаталогВладельца = Неопределено, ВерсияСсылка = Неопределено) Экспорт

	Результат = Новый Структура;
	Результат.Вставить("ДанныеПолучены", Ложь);
	Результат.Вставить("ДанныеФайла", Неопределено);
	Результат.Вставить("ТекстСообщения", "");
	Результат.Вставить("ФайлУжеРедактируетТекущийПользователь", Ложь);

	Результат.ДанныеФайла = ДанныеФайлаДляОткрытия(ФайлСсылка, ВерсияСсылка, УникальныйИдентификатор,
		РабочийКаталогВладельца);
	Если Не РаботаСФайламиКлиентСервер.МожноЛиЗанятьФайл(Результат.ДанныеФайла, Результат.ТекстСообщения) Тогда
		Возврат Результат;
	КонецЕсли;

	ПараметрыЗанятияФайла = РаботаСФайламиСлужебныйКлиентСервер.ПараметрыЗанятияФайла();
	ПараметрыЗанятияФайла.УникальныйИдентификатор = УникальныйИдентификатор;

	Результат.ФайлУжеРедактируетТекущийПользователь = Результат.ДанныеФайла.ФайлРедактируетТекущийПользователь;
	Если Не ЗначениеЗаполнено(Результат.ДанныеФайла.Редактирует) И Не ЗанятьФайл(Результат.ДанныеФайла,
		Результат.ТекстСообщения, ПараметрыЗанятияФайла) Тогда
		Возврат Результат;
	КонецЕсли;

	Результат.ДанныеПолучены = Истина;
	Возврат Результат;

КонецФункции

// Выполняет ПоместитьВоВременноеХранилище (если файл хранится в томе) и возвращает нужную ссылку.
//
// Параметры:
//   ВерсияСсылка - версия файла.
//   ИдентификаторФормы - уникальный идентификатор формы.
//
// Возвращаемое значение:
//   Строка  - навигационная ссылка во временном хранилище.
//
Функция ПолучитьНавигационнуюСсылкуДляОткрытия(ВерсияСсылка, ИдентификаторФормы = Неопределено) Экспорт

	ЕстьПраваНаОбъект = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(ВерсияСсылка, "Ссылка", Истина);

	Если ЕстьПраваНаОбъект = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;

	Возврат ПоместитьВоВременноеХранилище(РаботаСФайлами.ДвоичныеДанныеФайла(ВерсияСсылка));

КонецФункции

// Выполняет ДанныеФайла и вычисляет РабочийКаталогВладельца.
//
// Параметры:
//  ФайлИлиВерсияСсылка     - СправочникСсылка.Файлы
//                          - СправочникСсылка.ВерсииФайлов - файл или версия файла.
//  РабочийКаталогВладельца - Строка - в ней возвращается рабочий каталог владельца файла.
//
// Возвращаемое значение:
//   Структура - структура с данными файла:
//     * Ссылка - ОпределяемыйТип.ПрисоединенныйФайл
//
Функция ДанныеФайлаИРабочийКаталог(ФайлИлиВерсияСсылка, РабочийКаталогВладельца = Неопределено) Экспорт

	ФайлСсылка = Неопределено;
	ВерсияСсылка = Неопределено;
	ВозможностьХранитьВерсии = Ложь;
	Если ТипЗнч(ФайлИлиВерсияСсылка) = Тип("СправочникСсылка.ВерсииФайлов") Тогда
		ВерсияСсылка = ФайлИлиВерсияСсылка;
	Иначе
		ФайлСсылка = ФайлИлиВерсияСсылка;
		ВозможностьХранитьВерсии = ОбщегоНазначения.ЕстьРеквизитОбъекта("ТекущаяВерсия",
			ФайлИлиВерсияСсылка.Метаданные());
	КонецЕсли;

	ТекущаяВерсия = ?(Не ВозможностьХранитьВерсии, Неопределено, ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ФайлСсылка,
		"ТекущаяВерсия"));

	ПараметрыДанныхФайла = РаботаСФайламиКлиентСервер.ПараметрыДанныхФайла();
	ПараметрыДанныхФайла.ПолучатьСсылкуНаДвоичныеДанные = Ложь;

	ДанныеФайла = ДанныеФайла(ФайлИлиВерсияСсылка,, ПараметрыДанныхФайла);
	Если РабочийКаталогВладельца = Неопределено Тогда
		РабочийКаталогВладельца = РабочийКаталогПапки(ДанныеФайла.Владелец);
	КонецЕсли;

	ДанныеФайла.Вставить("РабочийКаталогВладельца", РабочийКаталогВладельца);
	Если РабочийКаталогВладельца <> "" Тогда

		ПолноеИмяФайлаВРабочемКаталоге = "";
		ИмяКаталога = ""; // Путь к локальному кэш здесь не используется.
		ВРабочемКаталогеНаЧтение = Истина; // не используется 
		ВРабочемКаталогеВладельца = Истина;

		Если ВерсияСсылка <> Неопределено Тогда
			ПолноеИмяФайлаВРабочемКаталоге = ПолноеИмяФайлаВРабочемКаталоге(ВерсияСсылка, ИмяКаталога,
				ВРабочемКаталогеНаЧтение, ВРабочемКаталогеВладельца);
		ИначеЕсли ВозможностьХранитьВерсии И ТекущаяВерсия <> Неопределено Тогда
			ПолноеИмяФайлаВРабочемКаталоге = ПолноеИмяФайлаВРабочемКаталоге(ТекущаяВерсия, ИмяКаталога,
				ВРабочемКаталогеНаЧтение, ВРабочемКаталогеВладельца);
		Иначе
			ПолноеИмяФайлаВРабочемКаталоге = ПолноеИмяФайлаВРабочемКаталоге(ФайлСсылка, ИмяКаталога,
				ВРабочемКаталогеНаЧтение, ВРабочемКаталогеВладельца);
		КонецЕсли;

		ДанныеФайла.Вставить("ПолноеИмяФайлаВРабочемКаталоге", ПолноеИмяФайлаВРабочемКаталоге);
	КонецЕсли;

	Возврат ДанныеФайла;
КонецФункции

// Делает ПолучитьДанныеФайла и вычисляет количество версий файла.
// Параметры:
//  ФайлСсылка  - СправочникСсылка.Файлы - файл.
//
// Возвращаемое значение:
//   Структура - структура с данными файла.
//
Функция ПолучитьДанныеФайлаИКоличествоВерсий(ФайлСсылка) Экспорт

	ПараметрыДанныхФайла = РаботаСФайламиКлиентСервер.ПараметрыДанныхФайла();
	ПараметрыДанныхФайла.ПолучатьСсылкуНаДвоичныеДанные = Ложь;

	ДанныеФайла = ДанныеФайла(ФайлСсылка,, ПараметрыДанныхФайла);
	КоличествоВерсий = ПолучитьКоличествоВерсий(ФайлСсылка);
	ДанныеФайла.Вставить("КоличествоВерсий", КоличествоВерсий);

	Возврат ДанныеФайла;

КонецФункции

// Освобождение Файла с получением данных.
// Параметры:
//  ФайлСсылка  - СправочникСсылка.Файлы - файл.
//  ДанныеФайла  - Структура - с данными файла.
//  УникальныйИдентификатор - уникальный идентификатор формы.
//
Процедура ПолучитьДанныеФайлаИОсвободитьФайл(ФайлСсылка, ДанныеФайла, УникальныйИдентификатор = Неопределено) Экспорт

	ДанныеФайла = ДанныеФайла(ФайлСсылка);
	ОсвободитьФайл(ДанныеФайла, УникальныйИдентификатор);

КонецПроцедуры

// Для записи изменений файла без его освобождения.
//
// Параметры:
//   ФайлСсылка                   - Структура - структура с данными файла.
//   СведенияОФайле               - см. РаботаСФайламиКлиентСервер.СведенияОФайле
//   ОтносительныйПутьКФайлу      - Строка    - относительный путь без пути рабочего каталога, например
//                                              "А1/Приказ.doc"; указывается, если НеМенятьЗаписьВРабочемКаталоге =
//                                              Ложь.
//   ПолныйПутьКФайлу             - Строка    - путь на клиенте в рабочем каталоге; указывается, если
//                                              НеМенятьЗаписьВРабочемКаталоге = Ложь.
//   ВРабочемКаталогеВладельца    - Булево    - файл находится в рабочем каталоге владельца.
//   УникальныйИдентификаторФормы - УникальныйИдентификатор - уникальный идентификатор формы.
//
// Возвращаемое значение:
//   Структура:
//     * Успешно     - Булево    - Истина, если создание версии выполнено (и файл бинарно изменен).
//     * ДанныеФайла - Структура - структура с данными файла.
//
Функция ПолучитьДанныеФайлаИСохранитьИзмененияФайла(ФайлСсылка, СведенияОФайле, ОтносительныйПутьКФайлу,
	ПолныйПутьКФайлу, ВРабочемКаталогеВладельца, УникальныйИдентификаторФормы = Неопределено) Экспорт

	ПараметрыДанныхФайла = РаботаСФайламиКлиентСервер.ПараметрыДанныхФайла();
	ПараметрыДанныхФайла.ПолучатьСсылкуНаДвоичныеДанные = Ложь;

	ДанныеФайла = ДанныеФайла(ФайлСсылка,, ПараметрыДанныхФайла);
	Если Не ДанныеФайла.ФайлРедактируетТекущийПользователь Тогда
		ВызватьИсключение НСтр("ru = 'Файл не занят текущим пользователем'");
	КонецЕсли;

	ВерсияСоздана = СохранитьИзмененияФайла(ФайлСсылка, СведенияОФайле, Ложь, ОтносительныйПутьКФайлу,
		ПолныйПутьКФайлу, ВРабочемКаталогеВладельца, УникальныйИдентификаторФормы);
	Возврат Новый Структура("Успешно,ДанныеФайла", ВерсияСоздана, ДанныеФайла);

КонецФункции

// Получает синтетический рабочий каталог папки на компьютере (он может прийти от родительской папки).
//
// Параметры:
//  СсылкаПапки  - СправочникСсылка.ПапкиФайлов - владелец файла.
//
// Возвращаемое значение:
//   Строка  - рабочий каталог.
//
Функция РабочийКаталогПапки(СсылкаПапки) Экспорт

	Если Не ЭтоСправочникФайлы(СсылкаПапки) Тогда
		Возврат "";
	КонецЕсли;

	УстановитьПривилегированныйРежим(Истина);

	РабочийКаталог = "";
	
	// Подготовить структуру отбора по измерениям.

	СтруктураОтбора = Новый Структура;
	СтруктураОтбора.Вставить("Папка", СсылкаПапки);
	СтруктураОтбора.Вставить("Пользователь", Пользователи.АвторизованныйПользователь());
	
	// Получить структуру с данными ресурсов записи.
	СтруктураРесурсов = РегистрыСведений.РабочиеКаталогиФайлов.Получить(СтруктураОтбора);
	
	// Получить путь из регистра
	РабочийКаталог = СтруктураРесурсов.Путь;

	Если Не ПустаяСтрока(РабочийКаталог) Тогда
		// Добавляем слэш в конце, если его нет.
		РабочийКаталог = ОбщегоНазначенияКлиентСервер.ДобавитьКонечныйРазделительПути(РабочийКаталог);
	КонецЕсли;

	Возврат РабочийКаталог;

КонецФункции

// Возвращаемое значение:
//   Структура:
//     * Файл                         - ОпределяемыйТип.ПрисоединенныйФайл
//     * Путь                         - Строка
//     * Размер                       - Число
//     * ДатаПомещенияВРабочийКаталог - Дата
//     * НаЧтение                     - Булево
//
Функция ФайлВРабочемКаталоге()

	Возврат Новый Структура("Файл, Путь, Размер, ДатаПомещенияВРабочийКаталог, НаЧтение");

КонецФункции

// Сохраняет в регистре сведений рабочий каталог папки и
// заменяет пути в регистре сведений ФайлыВРабочемКаталоге.
//
// Параметры:
//  СсылкаПапки  - СправочникСсылка.ПапкиФайлов - владелец файла.
//  РабочийКаталогПапки - Строка - рабочий каталог папки.
//  ИмяКаталогаПрежнееЗначение - Строка - прежнее значение рабочего каталога.
//
Процедура СохранитьРабочийКаталогПапкиИЗаменитьПутиВРегистре(СсылкаПапки, РабочийКаталогПапки,
	ИмяКаталогаПрежнееЗначение) Экспорт

	РаботаСФайламиСлужебный.СохранитьРабочийКаталогПапки(СсылкаПапки, РабочийКаталогПапки);

	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ
	|	ФайлыВРабочемКаталоге.Файл КАК Файл,
	|	ФайлыВРабочемКаталоге.Путь КАК Путь,
	|	ФайлыВРабочемКаталоге.Размер КАК Размер,
	|	ФайлыВРабочемКаталоге.ДатаПомещенияВРабочийКаталог КАК ДатаПомещенияВРабочийКаталог,
	|	ФайлыВРабочемКаталоге.НаЧтение КАК НаЧтение
	|ИЗ
	|	РегистрСведений.ФайлыВРабочемКаталоге КАК ФайлыВРабочемКаталоге
	|ГДЕ
	|	ФайлыВРабочемКаталоге.Пользователь = &Пользователь
	|	И ФайлыВРабочемКаталоге.ВРабочемКаталогеВладельца = ИСТИНА
	|	И ФайлыВРабочемКаталоге.Путь ПОДОБНО &Путь СПЕЦСИМВОЛ ""~""";

	Запрос.УстановитьПараметр("Пользователь", Пользователи.АвторизованныйПользователь());
	Запрос.УстановитьПараметр("Путь", ОбщегоНазначения.СформироватьСтрокуДляПоискаВЗапросе(ИмяКаталогаПрежнееЗначение)
		+ "%");
	УстановитьПривилегированныйРежим(Истина);
	РезультатЗапроса = Запрос.Выполнить();

	СписокДляЗамены = Новый Массив;

	Выборка = РезультатЗапроса.Выбрать();
	Пока Выборка.Следующий() Цикл

		НовыйПуть = Выборка.Путь;
		НовыйПуть = СтрЗаменить(НовыйПуть, ИмяКаталогаПрежнееЗначение, РабочийКаталогПапки);

		ФайлВРабочемКаталоге = ФайлВРабочемКаталоге();
		ФайлВРабочемКаталоге.Файл = Выборка.Файл;
		ФайлВРабочемКаталоге.Путь = НовыйПуть;
		ФайлВРабочемКаталоге.Размер = Выборка.Размер;
		ФайлВРабочемКаталоге.ДатаПомещенияВРабочийКаталог = Выборка.ДатаПомещенияВРабочийКаталог;
		ФайлВРабочемКаталоге.НаЧтение = Выборка.НаЧтение;

		СписокДляЗамены.Добавить(ФайлВРабочемКаталоге);

	КонецЦикла;

	Для Каждого ЭлементСписка Из СписокДляЗамены Цикл

		ВРабочемКаталогеВладельца = Истина;

		ФайлВРабочемКаталоге = ЭлементСписка; // см. ФайлВРабочемКаталоге
		ЗаписатьСтруктуруЗаписиВРегистр(
			ФайлВРабочемКаталоге.Файл, ФайлВРабочемКаталоге.Путь, ФайлВРабочемКаталоге.Размер,
			ФайлВРабочемКаталоге.ДатаПомещенияВРабочийКаталог, ФайлВРабочемКаталоге.НаЧтение, ВРабочемКаталогеВладельца);

	КонецЦикла;

КонецПроцедуры

// После смены пути запишем заново - с теми же значениями остальных полей.
// Параметры:
//  Версия - СправочникСсылка.ВерсииФайлов - версия.
//  Путь - Строка - относительный путь внутри рабочего каталога.
//  Размер  - размер файла в байтах.
//  ДатаПомещенияВРабочийКаталог - Дата - дата помещения файла в рабочий каталог.
//  НаЧтение - Булево - файл помещен на чтение.
//  ВРабочемКаталогеВладельца - Булево - файл в рабочем каталоге владельца (а не в основном рабочем каталоге).
//
Процедура ЗаписатьСтруктуруЗаписиВРегистр(Файл, Путь, Размер, ДатаПомещенияВРабочийКаталог, НаЧтение,
	ВРабочемКаталогеВладельца)

	ЕстьПраваНаОбъект = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(Файл, "Ссылка", Истина);

	Если ЕстьПраваНаОбъект = Неопределено Тогда
		Возврат;
	КонецЕсли;

	УстановитьПривилегированныйРежим(Истина);
	
	// Создать набор записей
	НаборЗаписей = РегистрыСведений.ФайлыВРабочемКаталоге.СоздатьНаборЗаписей();

	НаборЗаписей.Отбор.Файл.Установить(Файл);
	НаборЗаписей.Отбор.Пользователь.Установить(Пользователи.АвторизованныйПользователь());

	НоваяЗапись = НаборЗаписей.Добавить();
	НоваяЗапись.Файл = Файл;
	НоваяЗапись.Путь = Путь;
	НоваяЗапись.Размер = Размер;
	НоваяЗапись.ДатаПомещенияВРабочийКаталог = ДатаПомещенияВРабочийКаталог;
	НоваяЗапись.Пользователь = Пользователи.АвторизованныйПользователь();

	НоваяЗапись.НаЧтение = НаЧтение;
	НоваяЗапись.ВРабочемКаталогеВладельца = ВРабочемКаталогеВладельца;

	НаборЗаписей.Записать();

КонецПроцедуры

// Находит запись в регистре сведений ФайлыВРабочемКаталоге по относительному пути файла.
//
// Параметры:
//  ИмяФайла - Строка - имя файла с относительным путем (без пути к рабочему каталогу).
//
// Возвращаемое значение:
//  Структура:
//    Версия            - СправочникСсылка.ВерсииФайлов - найденная версия.
//    ДатаПомещения     - дата помещения файла в рабочий каталог.
//    Владелец          - ЛюбаяСсылка - владелец файла.
//    НомерВерсии       - Число - номер версии.
//    ВРегистреНаЧтение - Булево - значение ресурса НаЧтение.
//    ВРегистреКодФайла - число сюда помещается код файла.
//    ВРегистреПапка    - СправочникСсылка.ПапкиФайлов - папка файла.
//
Функция НайтиВРегистреПоПути(ИмяФайла) Экспорт

	УстановитьПривилегированныйРежим(Истина);

	Результат = Новый Структура;
	Результат.Вставить("ФайлЕстьВРегистре", Ложь);
	Результат.Вставить("Файл", Справочники.ВерсииФайлов.ПустаяСсылка());
	Результат.Вставить("ДатаПомещения");
	Результат.Вставить("Владелец");
	Результат.Вставить("НомерВерсии");
	Результат.Вставить("ВРегистреНаЧтение");
	Результат.Вставить("ВРегистреКодФайла");
	Результат.Вставить("ВРегистреПапка");
	
	// Для каждого по пути находим запись в регистре сведений - оттуда берем поле.
	// Версия и Размер и ДатаПомещенияВРабочийКаталог.

	АвторизованныйПользователь = Пользователи.АвторизованныйПользователь();

	Блокировка = Новый БлокировкаДанных;
	ЭлементБлокировки = Блокировка.Добавить("РегистрСведений.ФайлыВРабочемКаталоге");
	ЭлементБлокировки.УстановитьЗначение("Пользователь", АвторизованныйПользователь);
	ЭлементБлокировки.Режим = РежимБлокировкиДанных.Разделяемый;

	НачатьТранзакцию();
	Попытка

		Блокировка.Заблокировать();

		ЗапросВРегистр = Новый Запрос;
		ЗапросВРегистр.УстановитьПараметр("ИмяФайла", ИмяФайла);
		ЗапросВРегистр.УстановитьПараметр("Пользователь", АвторизованныйПользователь);
		ЗапросВРегистр.Текст =
		"ВЫБРАТЬ
		|	ФайлыВРабочемКаталоге.Файл КАК Файл,
		|	ФайлыВРабочемКаталоге.ДатаПомещенияВРабочийКаталог КАК ДатаПомещения,
		|	ФайлыВРабочемКаталоге.НаЧтение КАК ВРегистреНаЧтение,
		|	ВЫБОР
		|		КОГДА ТИПЗНАЧЕНИЯ(ФайлыВРабочемКаталоге.Файл) = ТИП(Справочник.ВерсииФайлов)
		|			ТОГДА ВЫРАЗИТЬ(ФайлыВРабочемКаталоге.Файл КАК Справочник.ВерсииФайлов).Владелец
		|		ИНАЧЕ ФайлыВРабочемКаталоге.Файл
		|	КОНЕЦ КАК Владелец,
		|	ВЫБОР
		|		КОГДА ТИПЗНАЧЕНИЯ(ФайлыВРабочемКаталоге.Файл) = ТИП(Справочник.ВерсииФайлов)
		|			ТОГДА ВЫРАЗИТЬ(ФайлыВРабочемКаталоге.Файл КАК Справочник.ВерсииФайлов).НомерВерсии
		|		ИНАЧЕ 0
		|	КОНЕЦ КАК НомерВерсии
		|ИЗ
		|	РегистрСведений.ФайлыВРабочемКаталоге КАК ФайлыВРабочемКаталоге
		|ГДЕ
		|	ФайлыВРабочемКаталоге.Путь = &ИмяФайла
		|	И ФайлыВРабочемКаталоге.Пользователь = &Пользователь";

		РезультатЗапроса = ЗапросВРегистр.Выполнить();
		Если Не РезультатЗапроса.Пустой() Тогда

			Выборка = РезультатЗапроса.Выбрать();
			Выборка.Следующий();

			ЗаполнитьЗначенияСвойств(Результат, Выборка);

			Результат.ФайлЕстьВРегистре = Истина;
			Результат.ВРегистреПапка = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(
				Выборка.Владелец, "ВладелецФайла");

		КонецЕсли;

		ЗафиксироватьТранзакцию();

	Исключение
		ОтменитьТранзакцию();
		ВызватьИсключение;
	КонецПопытки;

	Возврат Результат;

КонецФункции

// Находит в регистре сведений ФайлыВРабочемКаталоге информацию о ВерсииФайла: путь к файлу версии в рабочем каталоге,
// и статус - на чтение или на редактирование.
// 
// Параметры:
//  Версия - СправочникСсылка.ВерсииФайлов - версия.
//  ИмяКаталога - путь рабочего каталога.
//  ВРабочемКаталогеНаЧтение - Булево - файл помещен на чтение.
//  ВРабочемКаталогеВладельца - Булево - файл в рабочем каталоге владельца (а не в основном рабочем каталоге).
//
Функция ПолноеИмяФайлаВРабочемКаталоге(Знач Версия, Знач ИмяКаталога, ВРабочемКаталогеНаЧтение,
	ВРабочемКаталогеВладельца) Экспорт

	ЕстьПраваНаОбъект = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(Версия, "Ссылка", Истина);
	Если ЕстьПраваНаОбъект = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;

	УстановитьОтключениеБезопасногоРежима(Истина);
	УстановитьПривилегированныйРежим(Истина);

	СтруктураОтбора = Новый Структура;
	СтруктураОтбора.Вставить("Файл", Версия.Ссылка);
	СтруктураОтбора.Вставить("Пользователь", Пользователи.АвторизованныйПользователь());

	СтруктураРесурсов = РегистрыСведений.ФайлыВРабочемКаталоге.Получить(СтруктураОтбора);
	ПолноеИмяФайла = СтруктураРесурсов.Путь;
	ВРабочемКаталогеНаЧтение = СтруктураРесурсов.НаЧтение;
	ВРабочемКаталогеВладельца = СтруктураРесурсов.ВРабочемКаталогеВладельца;
	Если ПолноеИмяФайла <> "" И ВРабочемКаталогеВладельца = Ложь Тогда
		ОбщегоНазначения.СократитьИмяФайла(ПолноеИмяФайла);
		ПолноеИмяФайла = ИмяКаталога + ПолноеИмяФайла;
	КонецЕсли;

	Возврат ПолноеИмяФайла;

КонецФункции

// Записать в регистр сведений ФайлыВРабочемКаталоге информацию о пути файла.
// Параметры:
//  ТекущаяВерсия - СправочникСсылка.ВерсииФайлов - версия.
//  ПолноеИмяФайла - имя с путем в рабочем каталоге.
//  НаЧтение - Булево - файл помещен на чтение.
//  ВРабочемКаталогеВладельца - Булево - файл в рабочем каталоге владельца (а не в основном рабочем каталоге).
//
Процедура ЗаписатьПолноеИмяФайлаВРегистр(ТекущаяВерсия, ПолноеИмяФайла, НаЧтение, ВРабочемКаталогеВладельца) Экспорт

	УстановитьПривилегированныйРежим(Истина);
	
	// Создать набор записей
	НаборЗаписей = РегистрыСведений.ФайлыВРабочемКаталоге.СоздатьНаборЗаписей();

	НаборЗаписей.Отбор.Файл.Установить(ТекущаяВерсия.Ссылка);
	НаборЗаписей.Отбор.Пользователь.Установить(Пользователи.АвторизованныйПользователь());

	НоваяЗапись = НаборЗаписей.Добавить();
	НоваяЗапись.Файл = ТекущаяВерсия.Ссылка;
	НоваяЗапись.Путь = ПолноеИмяФайла;
	НоваяЗапись.Размер = ТекущаяВерсия.Размер;
	НоваяЗапись.ДатаПомещенияВРабочийКаталог = ТекущаяДатаСеанса();
	НоваяЗапись.Пользователь = Пользователи.АвторизованныйПользователь();

	НоваяЗапись.НаЧтение = НаЧтение;
	НоваяЗапись.ВРабочемКаталогеВладельца = ВРабочемКаталогеВладельца;

	НаборЗаписей.Записать();

КонецПроцедуры

// Удалить из регистра сведений ФайлыВРабочемКаталоге запись о данной версии файла.
// Параметры:
//  Версия - СправочникСсылка.ВерсииФайлов - версия.
//
Процедура УдалитьИзРегистра(Файл) Экспорт

	ЕстьПраваНаОбъект = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(Файл, "Ссылка", Истина);
	Если ЕстьПраваНаОбъект = Неопределено Тогда
		Возврат;
	КонецЕсли;

	УстановитьПривилегированныйРежим(Истина);

	НаборЗаписей = РегистрыСведений.ФайлыВРабочемКаталоге.СоздатьНаборЗаписей();

	НаборЗаписей.Отбор.Файл.Установить(Файл);
	НаборЗаписей.Отбор.Пользователь.Установить(Пользователи.АвторизованныйПользователь());

	НаборЗаписей.Записать();

КонецПроцедуры

// Удалить из регистра сведений ФайлыВРабочемКаталоге запись о старой версии и внести запись о новой.
// Параметры:
//  СтараяВерсия - СправочникСсылка.ВерсииФайлов - старая версия.
//  НоваяВерсия - СправочникСсылка.ВерсииФайлов - новая версия.
//  ПолноеИмяФайла - имя с путем в рабочем каталоге.
//  ИмяКаталога - путь рабочего каталога.
//  ВРабочемКаталогеВладельца - Булево - файл в рабочем каталоге владельца (а не в основном рабочем каталоге).
//
Процедура УдалитьВерсиюИЗанестиИнформациюФайлаВРегистр(СтараяВерсия, НоваяВерсия, ПолноеИмяФайла, ИмяКаталога,
	ВРабочемКаталогеВладельца)

	Если ОбщегоНазначения.ЭтоВебКлиент() Тогда
		Возврат;
	КонецЕсли;

	Если Не ЗначениеЗаполнено(НоваяВерсия) Тогда
		Возврат;
	КонецЕсли;

	УдалитьИзРегистра(СтараяВерсия);
	НаЧтение = Истина;
	ЗанестиИнформациюФайлаВРегистр(НоваяВерсия, ПолноеИмяФайла, ИмяКаталога, НаЧтение, 0, ВРабочемКаталогеВладельца);

КонецПроцедуры

// Записать в регистр сведений ФайлыВРабочемКаталоге информацию о пути файла.
// 
// Параметры:
//  Версия - СправочникСсылка.ВерсииФайлов - версия.
//  ПолныйПуть - Строка - полный путь файла.
//  ИмяКаталога - Строка - путь рабочего каталога.
//  НаЧтение - Булево - файл помещен на чтение.
//  РазмерФайла  - Число - размер файла в байтах.
//  ВРабочемКаталогеВладельца - Булево - файл в рабочем каталоге владельца (а не в основном рабочем каталоге).
//
Процедура ЗанестиИнформациюФайлаВРегистр(Версия, ПолныйПуть, ИмяКаталога, НаЧтение, РазмерФайла,
	ВРабочемКаталогеВладельца) Экспорт
	ПолноеИмяФайла = ПолныйПуть;

	Если ВРабочемКаталогеВладельца = Ложь Тогда
		Если СтрНайти(ПолныйПуть, ИмяКаталога) = 1 Тогда
			ПолноеИмяФайла = Сред(ПолныйПуть, СтрДлина(ИмяКаталога) + 1);
		КонецЕсли;
	КонецЕсли;

	ЕстьПраваНаОбъект = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(Версия, "Ссылка", Истина);

	Если ЕстьПраваНаОбъект = Неопределено Тогда
		Возврат;
	КонецЕсли;

	УстановитьПривилегированныйРежим(Истина);
	
	// Создать набор записей
	НаборЗаписей = РегистрыСведений.ФайлыВРабочемКаталоге.СоздатьНаборЗаписей();

	НаборЗаписей.Отбор.Файл.Установить(Версия.Ссылка);
	НаборЗаписей.Отбор.Пользователь.Установить(Пользователи.АвторизованныйПользователь());

	НоваяЗапись = НаборЗаписей.Добавить();
	НоваяЗапись.Файл = Версия.Ссылка;
	НоваяЗапись.Путь = ПолноеИмяФайла;

	Если РазмерФайла <> 0 Тогда
		НоваяЗапись.Размер = РазмерФайла;
	Иначе
		НоваяЗапись.Размер = Версия.Размер;
	КонецЕсли;

	НоваяЗапись.ДатаПомещенияВРабочийКаталог = ТекущаяДатаСеанса();
	НоваяЗапись.Пользователь = Пользователи.АвторизованныйПользователь();
	НоваяЗапись.НаЧтение = НаЧтение;
	НоваяЗапись.ВРабочемКаталогеВладельца = ВРабочемКаталогеВладельца;

	НаборЗаписей.Записать();

КонецПроцедуры

// Сортирует массив структур по полю Дата - на сервере, т.к. на тонком клиенте нет ТаблицаЗначений.
//
// Параметры:
//   МассивСтруктур - массив структур описаний файлов.
//
Процедура СортироватьМассивСтруктур(МассивСтруктур) Экспорт

	ТаблицаФайлов = Новый ТаблицаЗначений;
	ТаблицаФайлов.Колонки.Добавить("Путь");
	ТаблицаФайлов.Колонки.Добавить("Версия");
	ТаблицаФайлов.Колонки.Добавить("Размер");

	ТаблицаФайлов.Колонки.Добавить("ДатаПомещенияВРабочийКаталог", Новый ОписаниеТипов("Дата"));

	Для Каждого Строка Из МассивСтруктур Цикл
		НоваяСтрока = ТаблицаФайлов.Добавить();
		ЗаполнитьЗначенияСвойств(НоваяСтрока, Строка, "Путь, Размер, Версия, ДатаПомещенияВРабочийКаталог");
	КонецЦикла;
	
	// Сортировка по дате - в начале будут самые давно помещенные в рабочий каталог.
	ТаблицаФайлов.Сортировать("ДатаПомещенияВРабочийКаталог Возр");

	МассивСтруктурВозврат = Новый Массив;

	Для Каждого Строка Из ТаблицаФайлов Цикл
		Запись = Новый Структура;
		Запись.Вставить("Путь", Строка.Путь);
		Запись.Вставить("Размер", Строка.Размер);
		Запись.Вставить("Версия", Строка.Версия);
		Запись.Вставить("ДатаПомещенияВРабочийКаталог", Строка.ДатаПомещенияВРабочийКаталог);
		МассивСтруктурВозврат.Добавить(Запись);
	КонецЦикла;

	МассивСтруктур = МассивСтруктурВозврат;

КонецПроцедуры

// Функция меняет ВладелецФайла объектам типа Справочник.Файл, вернет Истина при успехе.
// Параметры:
//  МассивСсылокНаФайлы - Массив - массив файлов.
//  НовыйВладелецФайла  - ЛюбаяСсылка - новый владелец файла.
//
// Возвращаемое значение:
//   Булево  - успешно ли выполнена операция.
//
Функция УстановитьВладельцаФайла(МассивСсылокНаФайлы, НовыйВладелецФайла) Экспорт
	Если МассивСсылокНаФайлы.Количество() = 0 Или Не ЗначениеЗаполнено(НовыйВладелецФайла) Тогда
		Возврат Ложь;
	КонецЕсли;
	
	// Тот же родитель - ничего делать не надо.
	Если МассивСсылокНаФайлы.Количество() > 0 И (МассивСсылокНаФайлы[0].ВладелецФайла = НовыйВладелецФайла) Тогда
		Возврат Ложь;
	КонецЕсли;

	НачатьТранзакцию();
	Попытка
		Блокировка = Новый БлокировкаДанных;
		Для Каждого ФайлПринятый Из МассивСсылокНаФайлы Цикл
			ЭлементБлокировки = Блокировка.Добавить(Метаданные.НайтиПоТипу(ТипЗнч(ФайлПринятый)).ПолноеИмя());
			ЭлементБлокировки.УстановитьЗначение("Ссылка", ФайлПринятый);
		КонецЦикла;
		Блокировка.Заблокировать();

		Для Каждого ФайлПринятый Из МассивСсылокНаФайлы Цикл
			ФайлОбъект = ФайлПринятый.ПолучитьОбъект();
			ФайлОбъект.Заблокировать();
			ФайлОбъект.ВладелецФайла = НовыйВладелецФайла;
			ФайлОбъект.Записать();
		КонецЦикла;

		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		ВызватьИсключение;
	КонецПопытки;

	Возврат Истина;

КонецФункции

// Функция меняет свойство Родитель объектам типа Справочник.ПапкиФайла, вернет Истина при успехе, 
// в переменной НайденоЗацикливание вернет Истина, если одну из папок переносим в ее же дочернюю папку.
//
// Параметры:
//  МассивСсылокНаФайлы - Массив - массив файлов.
//  НовыйРодитель  - ЛюбаяСсылка - новый владелец файла.
//  НайденоЗацикливание - Булево - возвращает Истина, если найдено зацикливание.
//
// Возвращаемое значение:
//   Булево  - успешно ли выполнена операция.
//
Функция СменитьРодителяПапок(МассивСсылокНаФайлы, НовыйРодитель, НайденоЗацикливание) Экспорт
	НайденоЗацикливание = Ложь;

	Если МассивСсылокНаФайлы.Количество() = 0 Тогда
		Возврат Ложь;
	КонецЕсли;
	
	// Тот же родитель - ничего делать не надо.
	Если МассивСсылокНаФайлы.Количество() = 1 И (МассивСсылокНаФайлы[0].Родитель = НовыйРодитель) Тогда
		Возврат Ложь;
	КонецЕсли;

	Если ЕстьЗацикливание(МассивСсылокНаФайлы, НовыйРодитель) Тогда
		НайденоЗацикливание = Истина;
		Возврат Ложь;
	КонецЕсли;

	НачатьТранзакцию();
	Попытка
		Блокировка = Новый БлокировкаДанных;
		Для Каждого ФайлПринятый Из МассивСсылокНаФайлы Цикл
			ЭлементБлокировки = Блокировка.Добавить(Метаданные.НайтиПоТипу(ТипЗнч(ФайлПринятый)).ПолноеИмя());
			ЭлементБлокировки.УстановитьЗначение("Ссылка", ФайлПринятый);
		КонецЦикла;
		Блокировка.Заблокировать();

		Для Каждого ФайлПринятый Из МассивСсылокНаФайлы Цикл
			ФайлОбъект = ФайлПринятый.ПолучитьОбъект();
			ФайлОбъект.Заблокировать();
			ФайлОбъект.Родитель = НовыйРодитель;
			ФайлОбъект.Записать();
		КонецЦикла;

		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		ВызватьИсключение;
	КонецПопытки;

	Возврат Истина;

КонецФункции

// Получает данные файла для открытия и читает из общих настроек ПапкаДляСохранитьКак.
//
// Параметры:
//  ФайлИлиВерсияСсылка     - СправочникСсылка.Файлы
//                          - СправочникСсылка.ВерсииФайлов - файл или версия файла.
//  ИдентификаторФормы      - УникальныйИдентификатор - уникальный идентификатор формы.
//  РабочийКаталогВладельца - Строка - рабочий каталог владельца файла.
//
// Возвращаемое значение:
//   Структура - структура с данными файла.
//
Функция ДанныеФайлаДляСохранения(ФайлСсылка, ВерсияСсылка = Неопределено, ИдентификаторФормы = Неопределено,
	РабочийКаталогВладельца = Неопределено) Экспорт

	ДанныеФайла = ДанныеФайлаДляОткрытия(ФайлСсылка, ВерсияСсылка, ИдентификаторФормы, РабочийКаталогВладельца);

	ПапкаДляСохранитьКак = ОбщегоНазначения.ХранилищеОбщихНастроекЗагрузить("НастройкиПрограммы",
		"ПапкаДляСохранитьКак");
	ДанныеФайла.Вставить("ПапкаДляСохранитьКак", ПапкаДляСохранитьКак);

	Возврат ДанныеФайла;
КонецФункции

// Получает ДанныеФайла и НавигационнуюСсылкуВерсии всех подчиненных файлов.
// Параметры:
//  ФайлСсылка - СправочникСсылка.Файлы - файл.
//  ИдентификаторФормы - уникальный идентификатор формы.
//
// Возвращаемое значение:
//   Массив - массив структур с данными файлов.
//
Функция ДанныеФайлаИНавигационнаяСсылкаВсехВерсийФайла(ФайлСсылка, ИдентификаторФормы) Экспорт

	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ РАЗРЕШЕННЫЕ
	|	ВерсииФайлов.Ссылка КАК Ссылка
	|ИЗ
	|	Справочник.ВерсииФайлов КАК ВерсииФайлов
	|ГДЕ
	|	ВерсииФайлов.Владелец = &ФайлСсылка";

	Запрос.УстановитьПараметр("ФайлСсылка", ФайлСсылка);
	Результат = Запрос.Выполнить();
	Выборка = Результат.Выбрать();

	ПараметрыДанныхФайла = РаботаСФайламиКлиентСервер.ПараметрыДанныхФайла();
	ПараметрыДанныхФайла.ВызыватьИсключение = Ложь;
	ПараметрыДанныхФайла.ПолучатьСсылкуНаДвоичныеДанные = Ложь;

	МассивВозврата = Новый Массив;
	Пока Выборка.Следующий() Цикл

		ВерсияСсылка = Выборка.Ссылка;
		ДанныеФайла = ДанныеФайла(ФайлСсылка, ВерсияСсылка, ПараметрыДанныхФайла);

		Если ДанныеФайла.ПометкаУдаления = Ложь И Не ПрисоединенныйФайлНаходитсяНаДиске(ВерсияСсылка) Тогда

			Продолжить;
		КонецЕсли;

		НавигационнаяСсылкаВерсии = РаботаСФайламиСлужебный.ПолучитьНавигационнуюСсылкуВоВременномХранилище(
			ВерсияСсылка, ИдентификаторФормы);

		СтруктураВозврата = Новый Структура("ДанныеФайла, НавигационнаяСсылкаВерсии, ВерсияСсылка", ДанныеФайла,
			НавигационнаяСсылкаВерсии, ВерсияСсылка);
		МассивВозврата.Добавить(СтруктураВозврата);

	КонецЦикла;
	
	// Если не хранятся версии, то зашифровываем файл.
	ХранитьВерсии = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ФайлСсылка, "ХранитьВерсии");
	
	Если Не ХранитьВерсии 
		Или Не ЗначениеЗаполнено(ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ФайлСсылка, "ТекущаяВерсия")) Тогда
		
		ПараметрыДанныхФайла = РаботаСФайламиКлиентСервер.ПараметрыДанныхФайла();
		ПараметрыДанныхФайла.ПолучатьСсылкуНаДвоичныеДанные = Ложь;
		ДанныеФайла = ДанныеФайла(ФайлСсылка,, ПараметрыДанныхФайла);
		НавигационнаяСсылкаВерсии = РаботаСФайламиСлужебный.ПолучитьНавигационнуюСсылкуВоВременномХранилище(ФайлСсылка,
			ИдентификаторФормы);

		СтруктураВозврата = Новый Структура("ДанныеФайла, НавигационнаяСсылкаВерсии, ВерсияСсылка", ДанныеФайла,
			НавигационнаяСсылкаВерсии, ФайлСсылка);
		МассивВозврата.Добавить(СтруктураВозврата);
	КонецЕсли;

	Возврат МассивВозврата;
КонецФункции

// Добавляет подпись к версии файла и отмечает файл, как подписанный.
Процедура ДобавитьПодписьКФайлу(ФайлСсылка, СвойстваПодписи, ИдентификаторФормы) Экспорт

	СтруктураРеквизитов = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(ФайлСсылка, "Редактирует, Зашифрован");

	Редактирует = СтруктураРеквизитов.Редактирует;
	Если ЗначениеЗаполнено(Редактирует) Тогда
		ВызватьИсключение РаботаСФайламиСлужебныйКлиентСервер.СтрокаСообщенияОНедопустимостиПодписанияЗанятогоФайла(
			ФайлСсылка);
	КонецЕсли;

	Зашифрован = СтруктураРеквизитов.Зашифрован;
	Если Зашифрован Тогда
		СтрокаИсключения = РаботаСФайламиСлужебныйКлиентСервер.СтрокаСообщенияОНедопустимостиПодписанияЗашифрованногоФайла(
			ФайлСсылка);
		ВызватьИсключение СтрокаИсключения;
	КонецЕсли;

	Если Не ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ЭлектроннаяПодпись") Тогда
		Возврат;
	КонецЕсли;

	МодульЭлектроннаяПодпись = ОбщегоНазначения.ОбщийМодуль("ЭлектроннаяПодпись");
	МодульЭлектроннаяПодпись.ДобавитьПодпись(ФайлСсылка, СвойстваПодписи, ИдентификаторФормы);

КонецПроцедуры

Процедура ПоказыватьПодсказкиПриРедактированииФайлов(Значение = Неопределено) Экспорт

	УстановитьПривилегированныйРежим(Истина);
	Если Значение <> Неопределено Тогда
		ОбщегоНазначенияВызовСервера.ХранилищеОбщихНастроекСохранить(
			"НастройкиПрограммы", "ПоказыватьПодсказкиПриРедактированииФайлов", Значение,,, Истина);
		ОбновитьПовторноИспользуемыеЗначения();
	КонецЕсли;

КонецПроцедуры

#Область УдалениеДанныхФайловИВерсий

Функция РезультатУдаленияФайлов(ФайлыИлиВерсии, УникальныйИдентификатор) Экспорт

	УстановитьПривилегированныйРежим(Истина);

	АвторизованныйПользователь = Пользователи.АвторизованныйПользователь();
	РезультатУдаления = Новый Соответствие;
	Для Каждого ФайлИлиВерсия Из ФайлыИлиВерсии Цикл

		ЭтоВерсияФайла = ТипЗнч(ФайлИлиВерсия) = Тип("СправочникСсылка.ВерсииФайлов");
		Результат = Новый Структура("ТекстПредупреждения, Файлы", "", Новый Массив);
		Если ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ФайлИлиВерсия, "Автор") = АвторизованныйПользователь Тогда
			Если ЭтоВерсияФайла Тогда
				// @skip-check query-in-loop - Порционное удаление каждой версии в своей транзакции 
				УдалитьДанныеВерсии(ФайлИлиВерсия, УникальныйИдентификатор, Результат);
			Иначе
				// @skip-check query-in-loop - Порционное удаление каждого файла в своей транзакции 
				УдалитьДанныеФайла(ФайлИлиВерсия, УникальныйИдентификатор, Результат, АвторизованныйПользователь);
			КонецЕсли;
		Иначе
			Результат.ТекстПредупреждения = ?(ЭтоВерсияФайла, НСтр("ru = 'Только автор может удалить версию файла.'"),
				НСтр("ru = 'Только автор может удалить файл.'"));
		КонецЕсли;
		РезультатУдаления.Вставить(ФайлИлиВерсия, Результат);

	КонецЦикла;

	Возврат РезультатУдаления;

КонецФункции
Процедура УдалитьДанныеВерсии(ФайлИлиВерсия, УникальныйИдентификатор, Результат)

	БлокировкаДанных = Новый БлокировкаДанных;
	ЭлементБлокировкиДанных = БлокировкаДанных.Добавить(ФайлИлиВерсия.Метаданные().ПолноеИмя());
	ЭлементБлокировкиДанных.УстановитьЗначение("Ссылка", ФайлИлиВерсия);

	НачатьТранзакцию();
	Попытка

		БлокировкаДанных.Заблокировать();
		ПараметрыТекущейВерсииВладельца = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ФайлИлиВерсия, "Владелец,ТекущаяВерсия");
		Если ПараметрыТекущейВерсииВладельца.ТекущаяВерсия = ФайлИлиВерсия Тогда

			Запрос = Новый Запрос;
			Запрос.Текст =
			"ВЫБРАТЬ
			|	ВерсииФайлов.Ссылка КАК Ссылка
			|ИЗ
			|	Справочник.ВерсииФайлов КАК ВерсииФайлов
			|ГДЕ
			|	ВерсииФайлов.Владелец = &Владелец
			|	И ВерсииФайлов.Ссылка <> &Ссылка
			|	И НЕ ВерсииФайлов.ПометкаУдаления
			|
			|УПОРЯДОЧИТЬ ПО
			|	ВерсииФайлов.НомерВерсии УБЫВ";
			Запрос.УстановитьПараметр("Владелец", ПараметрыТекущейВерсииВладельца.Владелец);
			Запрос.УстановитьПараметр("Ссылка", ФайлИлиВерсия);
			ВерсииВладельца = Запрос.Выполнить().Выбрать();

			Если ВерсииВладельца.Следующий() Тогда
				РаботаСФайламиСлужебный.ОбновитьВерсиюВФайле(ПараметрыТекущейВерсииВладельца.Владелец,
					ВерсииВладельца.Ссылка, Неопределено, УникальныйИдентификатор);
			КонецЕсли;

		КонецЕсли;

		Результат.Файлы.Добавить(ФайлИлиВерсия);
		УдалитьДанные(ФайлИлиВерсия, УникальныйИдентификатор);
		ЗафиксироватьТранзакцию();

	Исключение
		ОтменитьТранзакцию();
		ВызватьИсключение;
	КонецПопытки;

КонецПроцедуры

Процедура УдалитьДанныеФайла(Файл, УникальныйИдентификатор, Результат, АвторизованныйПользователь)

	БлокировкаДанных = Новый БлокировкаДанных;
	ЭлементБлокировкиДанных = БлокировкаДанных.Добавить(Файл.Метаданные().ПолноеИмя());
	ЭлементБлокировкиДанных.УстановитьЗначение("Ссылка", Файл);
	
	ЕстьВерсииФайла = ТипЗнч(Файл) = Тип("СправочникСсылка.Файлы");
	Если ЕстьВерсииФайла Тогда
		ЭлементБлокировкиДанных = БлокировкаДанных.Добавить(Метаданные.Справочники.ВерсииФайлов.ПолноеИмя());
		ЭлементБлокировкиДанных.УстановитьЗначение("Владелец", Файл);
		ЭлементБлокировкиДанных.Режим = РежимБлокировкиДанных.Разделяемый;
	КонецЕсли;
	
	ЕстьВерсииФайла = Ложь;
	НачатьТранзакцию();
	Попытка
		БлокировкаДанных.Заблокировать();
		
		Если ЕстьВерсииФайла Тогда
			Запрос = Новый Запрос;
			Запрос.Текст =
			"ВЫБРАТЬ
			|	ВерсииФайлов.Ссылка КАК Ссылка,
			|	ВерсииФайлов.Автор КАК Автор
			|ИЗ
			|	Справочник.ВерсииФайлов КАК ВерсииФайлов
			|ГДЕ
			|	ВерсииФайлов.Владелец = &Владелец
			|
			|УПОРЯДОЧИТЬ ПО
			|	ВерсииФайлов.НомерВерсии УБЫВ";
			Запрос.УстановитьПараметр("Владелец", Файл);
			РезультатЗапроса = Запрос.Выполнить();
	
			ЕстьВерсииФайла = Не РезультатЗапроса.Пустой();
		КонецЕсли;
		
		Если ЕстьВерсииФайла Тогда
			Выборка = РезультатЗапроса.Выбрать();
		Иначе
			Результат.Файлы.Добавить(Файл);
			УдалитьДанные(Файл, УникальныйИдентификатор);
		КонецЕсли;
		ЗафиксироватьТранзакцию();

	Исключение
		ОтменитьТранзакцию();
		ВызватьИсключение;
	КонецПопытки;

	Если Не ЕстьВерсииФайла Тогда
		Возврат;
	КонецЕсли;

	ВерсияДругогоАвтора = Неопределено;
	Пока Выборка.Следующий() Цикл

		Если Выборка.Автор <> АвторизованныйПользователь Тогда
			Если ВерсияДругогоАвтора = Неопределено Тогда
				ВерсияДругогоАвтора = Выборка.Ссылка;
			КонецЕсли;
			Продолжить;
		КонецЕсли;

		Результат.Файлы.Добавить(Выборка.Ссылка);
		УдалитьДанные(Выборка.Ссылка, УникальныйИдентификатор);

	КонецЦикла;

	Если ВерсияДругогоАвтора <> Неопределено Тогда
		РаботаСФайламиСлужебный.ОбновитьВерсиюВФайле(Файл, ВерсияДругогоАвтора, Неопределено, УникальныйИдентификатор);
	Иначе
		Результат.Файлы.Добавить(Файл);
		УдалитьДанные(Файл, УникальныйИдентификатор);
	КонецЕсли;

КонецПроцедуры

Процедура УдалитьДанные(ФайлИлиВерсия, УникальныйИдентификатор)

	БлокировкаДанных = Новый БлокировкаДанных;
	ЭлементБлокировкиДанных = БлокировкаДанных.Добавить(ФайлИлиВерсия.Метаданные().ПолноеИмя());
	ЭлементБлокировкиДанных.УстановитьЗначение("Ссылка", ФайлИлиВерсия);

	НачатьТранзакцию();
	Попытка

		БлокировкаДанных.Заблокировать();
		ЗаблокироватьДанныеДляРедактирования(ФайлИлиВерсия,, УникальныйИдентификатор);

		ФайлИлиВерсияОбъект = ФайлИлиВерсия.ПолучитьОбъект();
		Если ФайлИлиВерсияОбъект.ТипХраненияФайла = Перечисления.ТипыХраненияФайлов.ВТомахНаДиске Тогда

			ПрисоединенныйФайлНаходитсяНаДиске = ПрисоединенныйФайлНаходитсяНаДиске(ФайлИлиВерсия);
			Если ПрисоединенныйФайлНаходитсяНаДиске Тогда

				СвойстваФайла = РаботаСФайламиВТомахСлужебный.СвойстваФайлаВТоме();
				ЗаполнитьЗначенияСвойств(СвойстваФайла, ФайлИлиВерсияОбъект);
				РаботаСФайламиВТомахСлужебный.УдалитьФайл(РаботаСФайламиВТомахСлужебный.ПолноеИмяФайлаВТоме(
					СвойстваФайла));

			КонецЕсли;
			// Изменяем путь к файлу, чтобы он был уникален.
			// Т.к. данные на компьютере удалены, то корректность расширения не сохраняем.
			ФайлИлиВерсияОбъект.ПутьКФайлу = ФайлИлиВерсияОбъект.ПутьКФайлу + "_remove";//@Non-NLS
		Иначе
			РаботаСФайламиСлужебный.УдалитьЗаписьИзРегистраДвоичныеДанныеФайлов(ФайлИлиВерсия);
		КонецЕсли;

		ФайлИлиВерсияОбъект.ПометкаУдаления = Истина;
		ФайлИлиВерсияОбъект.ДополнительныеСвойства.Вставить("УдалениеДанных", Истина);
		ФайлИлиВерсияОбъект.Записать();

		РазблокироватьДанныеДляРедактирования(ФайлИлиВерсия, УникальныйИдентификатор);
		ЗафиксироватьТранзакцию();

	Исключение
		ОтменитьТранзакцию();
		РазблокироватьДанныеДляРедактирования(ФайлИлиВерсия, УникальныйИдентификатор);
		ВызватьИсключение;
	КонецПопытки;

КонецПроцедуры

#КонецОбласти

// Информационные

// Функция возвращает количество Файлов, занятых текущим пользователем
// в разрезе владельца.
// Параметры:
//  ВладелецФайла  - ЛюбаяСсылка - владелец файла.
//
// Возвращаемое значение:
//   Число  - количество занятых файлов.
//
Функция КоличествоФайловЗанятыхТекущимПользователем(ВладелецФайла) Экспорт

	Возврат РаботаСФайламиСлужебный.КоличествоЗанятыхФайлов(ВладелецФайла);

КонецФункции

// Получает количество версий файла.
// Параметры:
//  ФайлСсылка - СправочникСсылка.Файлы - файл.
//
// Возвращаемое значение:
//   Число - число версий
//
Функция ПолучитьКоличествоВерсий(ФайлСсылка)

	УстановитьПривилегированныйРежим(Истина);

	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ
	|	КОЛИЧЕСТВО(*) КАК Количество
	|ИЗ
	|	Справочник.ВерсииФайлов КАК ВерсииФайлов
	|ГДЕ
	|	ВерсииФайлов.Владелец = &ФайлСсылка";

	Запрос.УстановитьПараметр("ФайлСсылка", ФайлСсылка);
	Выборка = Запрос.Выполнить().Выбрать();
	Выборка.Следующий();

	Возврат Число(Выборка.Количество);

КонецФункции

// Вернет Истина если есть зацикливание (если одну из папок переносим в ее же дочернюю папку).
// Параметры:
//  МассивСсылокНаФайлы - Массив - массив файлов.
//  НовыйРодитель  - ЛюбаяСсылка - новый владелец файла.
//
// Возвращаемое значение:
//   Булево  - есть зацикливание.
//
Функция ЕстьЗацикливание(Знач МассивСсылокНаФайлы, НовыйРодитель)

	Если МассивСсылокНаФайлы.Найти(НовыйРодитель) <> Неопределено Тогда
		Возврат Истина; // нашли зацикливание
	КонецЕсли;

	Запрос = Новый Запрос;
	Запрос.Текст = "ВЫБРАТЬ
				   |	ПапкиФайлов.Родитель КАК Родитель
				   |ИЗ
				   |	Справочник.ПапкиФайлов КАК ПапкиФайлов
				   |ГДЕ
				   |	ПапкиФайлов.Ссылка = &Ссылка
				   |ИТОГИ
				   |ПО
				   |	Родитель ТОЛЬКО ИЕРАРХИЯ";

	Запрос.УстановитьПараметр("Ссылка", НовыйРодитель);

	Родители = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Родитель");

	СсылкиНаФайлыБезРодителей = ОбщегоНазначенияКлиентСервер.РазностьМассивов(МассивСсылокНаФайлы, Родители);

	Возврат СсылкиНаФайлыБезРодителей.Количество() <> МассивСсылокНаФайлы.Количество();

КонецФункции

// Возвращает Истина, если в указанном элементе справочника ПапкиФайлов есть дочерний элемент с таким именем.
//
// Параметры:
//  ИмяПапки					 - Строка					     - имя папки
//  Родитель					 - ОпределяемыйТип.ВладелецПрисоединенныхФайлов	 - родитель папки.
//  ПерваяПапкаСТакимЖеИменем	 - ОпределяемыйТип.ВладелецПрисоединенныхФайлов	 - первая же найденная папка с указанным именем.
// 
// Возвращаемое значение:
//  Булево - есть дочерний элемент с таким именем.
//
Функция ЕстьПапкаСТакимИменем(ИмяПапки, Родитель, ПерваяПапкаСТакимЖеИменем) Экспорт

	ПерваяПапкаСТакимЖеИменем = Справочники.ПапкиФайлов.ПустаяСсылка();

	ВыборкаЗапроса = ЗапросВПапки(ИмяПапки, Родитель);

	Если ВыборкаЗапроса.Количество() > 0 Тогда
		ПерваяПапкаСТакимЖеИменем = ВыборкаЗапроса.Ссылка;
		Возврат Истина;
	КонецЕсли;

	Возврат Ложь;

КонецФункции

// Возвращаемое значение:
//  Структура:
//   * Ссылка - ЛюбаяСсылка.
// 
Функция ЗапросВПапки(Знач ИмяПапки, Родитель)
	ЗапросВПапки = Новый Запрос;
	ЗапросВПапки.УстановитьПараметр("Наименование", ИмяПапки);
	ЗапросВПапки.УстановитьПараметр("Родитель", Родитель);
	ЗапросВПапки.Текст =
	"ВЫБРАТЬ РАЗРЕШЕННЫЕ ПЕРВЫЕ 1
	|	ПапкиФайлов.Ссылка КАК Ссылка
	|ИЗ
	|	Справочник.ПапкиФайлов КАК ПапкиФайлов
	|ГДЕ
	|	ПапкиФайлов.Наименование = &Наименование
	|	И ПапкиФайлов.Родитель = &Родитель";

	Если Родитель <> Неопределено И ТипЗнч(Родитель) <> Тип("СправочникСсылка.ПапкиФайлов") Тогда
		ИмяСправочникаХранилищаФайлов = РаботаСФайламиСлужебный.ИмяСправочникаХраненияФайлов(Родитель);
		ЗапросВПапки.Текст = СтрЗаменить(ЗапросВПапки.Текст, ".ПапкиФайлов", "." + ИмяСправочникаХранилищаФайлов);
	КонецЕсли;

	РезультатЗапроса = ЗапросВПапки.Выполнить();
	ВыборкаЗапроса = РезультатЗапроса.Выбрать();
	ВыборкаЗапроса.Следующий();
	Возврат ВыборкаЗапроса
КонецФункции

Функция ФайлСинхронизируетсяОблачнымСервисом(Файл)

	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ ПЕРВЫЕ 1
	|	КОЛИЧЕСТВО(СтатусыСинхронизацииФайловСОблачнымСервисом.Файл) КАК Файл
	|ИЗ
	|	РегистрСведений.СтатусыСинхронизацииФайловСОблачнымСервисом КАК СтатусыСинхронизацииФайловСОблачнымСервисом
	|ГДЕ
	|	СтатусыСинхронизацииФайловСОблачнымСервисом.Файл = &Файл";

	Запрос.УстановитьПараметр("Файл", Файл);

	РезультатЗапроса = Запрос.Выполнить();
	Если РезультатЗапроса.Пустой() Тогда
		Возврат Ложь;
	КонецЕсли;

	Возврат Истина;

КонецФункции

Функция ЕстьПравоДоступа(Право, Ссылка) Экспорт

	Возврат ПравоДоступа(Право, Ссылка.Метаданные());

КонецФункции

Функция ПараметрыДобавленияИзображения(ВладелецФайлов, РеквизитРазмещения = Неопределено) Экспорт

	ПараметрыДобавления = Новый Структура;
	ПараметрыДобавления.Вставить("ПравоДобавления", ЕстьПравоДоступа("Добавление", ВладелецФайлов)); // @Access-right-2
	ПараметрыДобавления.Вставить("ПравоИзменения", ЕстьПравоДоступа("Изменение", ВладелецФайлов)); // @Access-right-2
	ПараметрыДобавления.Вставить("ФайлыВладельца", КоличествоПрисоединенныхФайлов(ВладелецФайлов, Истина,
		РеквизитРазмещения));
	Возврат ПараметрыДобавления;

КонецФункции

////////////////////////////////////////////////////////////////////////////////
// Обновление информационной базы.

// Создает новые файлы по аналогии с указанными.
// Параметры:
//  МассивФайлов  - Массив - массив объектов СправочникСсылка.Файлы - существующие файлы.
//  ВладелецНовогоФайла - ЛюбаяСсылка - владелец файла.
//
Процедура СкопироватьФайлы(МассивФайлов, ВладелецНовогоФайла) Экспорт

	Для Каждого Файл Из МассивФайлов Цикл
		СкопироватьФайл(Файл, ВладелецНовогоФайла);
	КонецЦикла;

КонецПроцедуры

// Записывает ХранилищеФайла в информационную базу.
//
// Параметры:
//   ВерсияСсылка - ссылка на версию файла.
//   ХранилищеФайла - ХранилищеЗначения, с двоичными данными файла, которые требуется записать.
//
Процедура ЗаписатьФайлВИнформационнуюБазу(ВерсияСсылка, ХранилищеФайла)

	УстановитьПривилегированныйРежим(Истина);

	МенеджерЗаписи = РегистрыСведений.ДвоичныеДанныеФайлов.СоздатьМенеджерЗаписи();
	МенеджерЗаписи.Файл = ВерсияСсылка;
	МенеджерЗаписи.ДвоичныеДанныеФайла = ХранилищеФайла;
	МенеджерЗаписи.Записать(Истина);

КонецПроцедуры

// Ставит файлу признак Зашифрован.
Процедура УстановитьПризнакЗашифрован(ФайлСсылка, Зашифрован, УникальныйИдентификатор = Неопределено) Экспорт

	НачатьТранзакцию();
	Попытка
		БлокировкаДанных = Новый БлокировкаДанных;
		ЭлементБлокировкиДанных = БлокировкаДанных.Добавить(Метаданные.НайтиПоТипу(ТипЗнч(ФайлСсылка)).ПолноеИмя());
		ЭлементБлокировкиДанных.УстановитьЗначение("Ссылка", ФайлСсылка);
		БлокировкаДанных.Заблокировать();

		ФайлОбъект = ФайлСсылка.ПолучитьОбъект();
		ЗаблокироватьДанныеДляРедактирования(ФайлСсылка,, УникальныйИдентификатор);

		ФайлОбъект.Зашифрован = Зашифрован;
		// Чтобы прошла запись ранее подписанного объекта.
		ФайлОбъект.ДополнительныеСвойства.Вставить("ЗаписьПодписанногоОбъекта", Истина);
		ФайлОбъект.Записать();
		РазблокироватьДанныеДляРедактирования(ФайлСсылка, УникальныйИдентификатор);
		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		РазблокироватьДанныеДляРедактирования(ФайлСсылка, УникальныйИдентификатор);
		ВызватьИсключение;
	КонецПопытки;

КонецПроцедуры

// Обновляет размер файла и текущей версии.
//
// Параметры:
//   ДанныеФайла - см. ДанныеФайла
//   РазмерФайла - Число
//   ИдентификаторФормы - УникальныйИдентификатор
//
Процедура ОбновитьРазмерФайлаИВерсии(ДанныеФайла, РазмерФайла, ИдентификаторФормы) Экспорт

	УказанаВерсияФайла = ДанныеФайла.Версия <> ДанныеФайла.Ссылка;

	Блокировка = Новый БлокировкаДанных;
	ЭлементБлокировки = Блокировка.Добавить(ДанныеФайла.Ссылка.Метаданные().ПолноеИмя());
	ЭлементБлокировки.УстановитьЗначение("Ссылка", ДанныеФайла.Ссылка);
	Если УказанаВерсияФайла Тогда
		ЭлементБлокировки = Блокировка.Добавить(ДанныеФайла.Версия.Метаданные().ПолноеИмя());
		ЭлементБлокировки.УстановитьЗначение("Ссылка", ДанныеФайла.Версия);
	КонецЕсли;

	НачатьТранзакцию();
	Попытка

		Блокировка.Заблокировать();
		ЗаблокироватьДанныеДляРедактирования(ДанныеФайла.Ссылка,, ИдентификаторФормы);
		Если УказанаВерсияФайла Тогда
			ЗаблокироватьДанныеДляРедактирования(ДанныеФайла.Версия,, ИдентификаторФормы);
		КонецЕсли;

		ВерсияОбъект = ДанныеФайла.Версия.ПолучитьОбъект();
		ВерсияОбъект.Размер = РазмерФайла;
		// Чтобы прошла запись подписанного объекта.
		ВерсияОбъект.ДополнительныеСвойства.Вставить("ЗаписьПодписанногоОбъекта", Истина);
		ВерсияОбъект.Записать();

		Если УказанаВерсияФайла Тогда
			ФайлОбъект = ДанныеФайла.Ссылка.ПолучитьОбъект();
			// Чтобы прошла запись подписанного объекта.
			ФайлОбъект.ДополнительныеСвойства.Вставить("ЗаписьПодписанногоОбъекта", Истина);
			ФайлОбъект.Записать();
		КонецЕсли;

		РазблокироватьДанныеДляРедактирования(ДанныеФайла.Ссылка, ИдентификаторФормы);
		Если УказанаВерсияФайла Тогда
			РазблокироватьДанныеДляРедактирования(ДанныеФайла.Версия, ИдентификаторФормы);
		КонецЕсли;

		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		РазблокироватьДанныеДляРедактирования(ДанныеФайла.Ссылка, ИдентификаторФормы);
		Если УказанаВерсияФайла Тогда
			РазблокироватьДанныеДляРедактирования(ДанныеФайла.Версия, ИдентификаторФормы);
		КонецЕсли;
		ВызватьИсключение;
	КонецПопытки;

КонецПроцедуры

Процедура ЗаписатьКодировкуВерсииФайла(ВерсияСсылка, Кодировка) Экспорт

	РегистрыСведений.КодировкиФайлов.ЗаписатьКодировкуВерсииФайла(ВерсияСсылка, Кодировка);

КонецПроцедуры

// Записывает кодировку версии файла.
//
// Параметры:
//   ВерсияСсылка - ссылка на версию файла.
//   Кодировка - строка кодировки.
//   ИзвлеченныйТекст - текст, извлеченный из файла.
//
Процедура ЗаписатьКодировкуВерсииФайлаИИзвлеченныйТекст(ВерсияСсылка, Кодировка, ИзвлеченныйТекст) Экспорт

	РегистрыСведений.КодировкиФайлов.ЗаписатьКодировкуВерсииФайла(ВерсияСсылка, Кодировка);
	ЗаписатьРезультатИзвлеченияТекстаПриРедактировании(ВерсияСсылка, Перечисления.СтатусыИзвлеченияТекстаФайлов.Извлечен,
		ИзвлеченныйТекст);

КонецПроцедуры

// Записывает на сервер результат извлечения текста - извлеченный текст и СтатусИзвлеченияТекста.
Процедура ЗаписатьРезультатИзвлеченияТекстаПриРедактировании(ВерсияСсылка, РезультатИзвлечения,
	АдресВременногоХранилищаТекста)

	ФайлЗаблокирован = Ложь;

	МетаданныеВерсии = Метаданные.НайтиПоТипу(ТипЗнч(ВерсияСсылка));
	Если ОбщегоНазначения.ЕстьРеквизитОбъекта("РодительскаяВерсия", МетаданныеВерсии) Тогда
		ЗапрашиваемыеРеквизиты = Новый Структура;
		ЗапрашиваемыеРеквизиты.Вставить("Владелец", "Владелец");
		ЗапрашиваемыеРеквизиты.Вставить("ТекущаяВерсия", "Владелец.ТекущаяВерсия");
		РеквизитыФайла = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(ВерсияСсылка, ЗапрашиваемыеРеквизиты);
		Файл = РеквизитыФайла.Владелец;
		Если РеквизитыФайла.ТекущаяВерсия = ВерсияСсылка Тогда

			Попытка
				ЗаблокироватьДанныеДляРедактирования(Файл);
				ФайлЗаблокирован = Истина;
			Исключение
				// Исключение, если объект уже заблокирован, в том числе и методом Заблокировать.
				Возврат;
			КонецПопытки;

		КонецЕсли;
	Иначе
		Файл = ВерсияСсылка;
	КонецЕсли;

	ИспользованиеПолнотекстовогоПоиска = Метаданные.СвойстваОбъектов.ИспользованиеПолнотекстовогоПоиска.Использовать;

	НачатьТранзакцию();
	Попытка
		Если ТипЗнч(Файл) = Тип("СправочникСсылка.Файлы") Тогда
			ФайлДляСравнения = РеквизитыФайла.ТекущаяВерсия;
		Иначе
			ФайлДляСравнения = ВерсияСсылка;
		КонецЕсли;

		БлокировкаВерсии = Новый БлокировкаДанных;
		ЭлементБлокировкиДанных = БлокировкаВерсии.Добавить(Метаданные.НайтиПоТипу(ТипЗнч(ВерсияСсылка)).ПолноеИмя());
		ЭлементБлокировкиДанных.УстановитьЗначение("Ссылка", ВерсияСсылка);

		Если ФайлДляСравнения = ВерсияСсылка Тогда
			БлокировкаФайла = Новый БлокировкаДанных;
			ЭлементБлокировкиДанных = БлокировкаФайла.Добавить(Метаданные.НайтиПоТипу(ТипЗнч(Файл)).ПолноеИмя());
			ЭлементБлокировкиДанных.УстановитьЗначение("Ссылка", Файл);
			БлокировкаФайла.Заблокировать();
		КонецЕсли;

		БлокировкаВерсии.Заблокировать();

		ВерсияОбъект = ВерсияСсылка.ПолучитьОбъект();

		Если МетаданныеВерсии.ПолнотекстовыйПоиск = ИспользованиеПолнотекстовогоПоиска Тогда
			Если Не ПустаяСтрока(АдресВременногоХранилищаТекста) Тогда

				Если Не ЭтоАдресВременногоХранилища(АдресВременногоХранилищаТекста) Тогда
					ВерсияОбъект.ТекстХранилище = Новый ХранилищеЗначения(АдресВременногоХранилищаТекста,
						Новый СжатиеДанных(9));
					ВерсияОбъект.СтатусИзвлеченияТекста = Перечисления.СтатусыИзвлеченияТекстаФайлов.Извлечен;
				Иначе
					РезультатИзвлеченияТекста = РаботаСФайламиСлужебный.ИзвлечьТекст(АдресВременногоХранилищаТекста);
					ВерсияОбъект.ТекстХранилище = РезультатИзвлеченияТекста.ТекстХранилище;
					ВерсияОбъект.СтатусИзвлеченияТекста = РезультатИзвлеченияТекста.СтатусИзвлеченияТекста;
				КонецЕсли;

			КонецЕсли;
		Иначе
			ВерсияОбъект.ТекстХранилище = Новый ХранилищеЗначения("");
			ВерсияОбъект.СтатусИзвлеченияТекста = Перечисления.СтатусыИзвлеченияТекстаФайлов.НеИзвлечен;
		КонецЕсли;

		Если РезультатИзвлечения = "НеИзвлечен" Тогда
			ВерсияОбъект.СтатусИзвлеченияТекста = Перечисления.СтатусыИзвлеченияТекстаФайлов.НеИзвлечен;
		ИначеЕсли РезультатИзвлечения = "Извлечен" Тогда
			ВерсияОбъект.СтатусИзвлеченияТекста = Перечисления.СтатусыИзвлеченияТекстаФайлов.Извлечен;
		ИначеЕсли РезультатИзвлечения = "ИзвлечьНеУдалось" Тогда
			ВерсияОбъект.СтатусИзвлеченияТекста = Перечисления.СтатусыИзвлеченияТекстаФайлов.ИзвлечьНеУдалось;
		КонецЕсли;
	
		// Чтобы прошла запись ранее подписанного объекта.
		ВерсияОбъект.ДополнительныеСвойства.Вставить("ЗаписьПодписанногоОбъекта", Истина);
		ВерсияОбъект.Записать();

		Если ФайлДляСравнения = ВерсияСсылка Тогда
			ФайлОбъект = Файл.ПолучитьОбъект();
			ФайлОбъект.ТекстХранилище = ВерсияОбъект.ТекстХранилище;
			// Чтобы прошла запись ранее подписанного объекта.
			ФайлОбъект.ДополнительныеСвойства.Вставить("ЗаписьПодписанногоОбъекта", Истина);
			ФайлОбъект.Записать();
		КонецЕсли;

		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();

		Если ФайлЗаблокирован Тогда
			РазблокироватьДанныеДляРедактирования(Файл);
		КонецЕсли;

		ВызватьИсключение;
	КонецПопытки;

	Если ФайлЗаблокирован Тогда
		РазблокироватьДанныеДляРедактирования(Файл);
	КонецЕсли;

КонецПроцедуры

//////////////////////////////////////////////////////////////////////////////////////////////////
///// Общие файловые функции
// См. эту процедуру в модуле РаботаСФайламиСлужебный.
//
Процедура ЗаписатьРезультатИзвлеченияТекста(ФайлИлиВерсияСсылка, РезультатИзвлечения, АдресВременногоХранилищаТекста) Экспорт

	РаботаСФайламиСлужебный.ЗаписатьРезультатИзвлеченияТекста(
		ФайлИлиВерсияСсылка, РезультатИзвлечения, АдресВременногоХранилищаТекста);

КонецПроцедуры

// Только для внутреннего использования.
Процедура ПроверитьПодписи(ИсходныеДанные, ДанныеСтрок, ПодписанныйОбъект) Экспорт

	Если Не ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ЭлектроннаяПодпись") Тогда
		Возврат;
	КонецЕсли;
	МодульЭлектроннаяПодпись = ОбщегоНазначения.ОбщийМодуль("ЭлектроннаяПодпись");
	МодульЭлектроннаяПодписьКлиентСервер = ОбщегоНазначения.ОбщийМодуль("ЭлектроннаяПодписьКлиентСервер");

	Для Каждого СтрокаПодписи Из ДанныеСтрок Цикл

		РезультатПроверкиПодписи = МодульЭлектроннаяПодписьКлиентСервер.РезультатПроверкиПодписи();
		ОписаниеОшибки = "";
		МодульЭлектроннаяПодпись.ПроверитьПодпись(Неопределено, ИсходныеДанные,
			СтрокаПодписи.АдресПодписи, ОписаниеОшибки, СтрокаПодписи.ДатаПодписи, РезультатПроверкиПодписи);

		СтрокаПодписи.ДатаПроверкиПодписи = ТекущаяДатаСеанса();
		СтрокаПодписи.ПодписьВерна      = (РезультатПроверкиПодписи.Результат = Истина);
		СтрокаПодписи.ОписаниеОшибки    = ОписаниеОшибки;
		СтрокаПодписи.ТребуетсяПроверка = РезультатПроверкиПодписи.ТребуетсяПроверка;
		Если ЗначениеЗаполнено(РезультатПроверкиПодписи.ТипПодписи) Тогда
			СтрокаПодписи.ТипПодписи        = РезультатПроверкиПодписи.ТипПодписи;
		КонецЕсли;
		Если ЗначениеЗаполнено(РезультатПроверкиПодписи.СрокДействияПоследнейМеткиВремени) Тогда
			СтрокаПодписи.СрокДействияПоследнейМеткиВремени = РезультатПроверкиПодписи.СрокДействияПоследнейМеткиВремени;
		КонецЕсли;
		
		// Локализация

		Если ЗначениеЗаполнено(СтрокаПодписи.РезультатПроверкиПодписиПоМЧД) И ОбщегоНазначения.ПодсистемаСуществует(
			"СтандартныеПодсистемы.МашиночитаемыеДоверенности") Тогда
			МодульМашиночитаемыеДоверенностиФНССлужебный = ОбщегоНазначения.ОбщийМодуль(
				"МашиночитаемыеДоверенностиФНССлужебный");

			РезультатПроверкиДоверенностей = ПолучитьИзВременногоХранилища(СтрокаПодписи.РезультатПроверкиПодписиПоМЧД);
			НовыйРезультатПроверкиДоверенностей = Новый Массив;
			Для Каждого Результат Из РезультатПроверкиДоверенностей Цикл
				РезультатПроверкиПодписиПоМЧД = МодульМашиночитаемыеДоверенностиФНССлужебный.РезультатПроверкиПодписиПоМЧД(
					Результат.МашиночитаемаяДоверенность, ПодписанныйОбъект, РезультатПроверкиПодписи.Сертификат,
					СтрокаПодписи.ДатаПодписи);
				НовыйРезультатПроверкиДоверенностей.Добавить(РезультатПроверкиПодписиПоМЧД);
				СтрокаПодписи.РезультатПроверкиДоверенностей = ПоместитьВоВременноеХранилище(
					НовыйРезультатПроверкиДоверенностей, СтрокаПодписи.РезультатПроверкиПодписиПоМЧД);
			КонецЦикла;
		КонецЕсли;
			
		// Конец Локализация

		РаботаСФайламиСлужебныйКлиентСервер.ЗаполнитьСтатусПодписи(СтрокаПодписи, ТекущаяДатаСеанса());
	КонецЦикла;

КонецПроцедуры

// Локализация

Функция ПроверитьПодписиПоМЧД(Подписи, ПодписанныйОбъект) Экспорт

	РезультатыПроверок = Новый Массив;

	Если Не ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.МашиночитаемыеДоверенности") Тогда
		Возврат Новый Массив;
	КонецЕсли;

	МодульМашиночитаемыеДоверенностиФНССлужебный = ОбщегоНазначения.ОбщийМодуль(
			"МашиночитаемыеДоверенностиФНССлужебный");
	Для Каждого Подпись Из Подписи Цикл

		РезультатПроверкиДоверенностей = ПолучитьИзВременногоХранилища(Подпись.РезультатПроверкиПодписиПоМЧД);
		НовыйРезультатПроверкиДоверенностей = Новый Массив;
		Для Каждого Результат Из РезультатПроверкиДоверенностей Цикл
			РезультатПроверкиПодписиПоМЧД = МодульМашиночитаемыеДоверенностиФНССлужебный.РезультатПроверкиПодписиПоМЧД(
					Результат.МашиночитаемаяДоверенность, ПодписанныйОбъект, Подпись.Сертификат, Подпись.ДатаПодписи);
			НовыйРезультатПроверкиДоверенностей.Добавить(РезультатПроверкиПодписиПоМЧД);
		КонецЦикла;

		РезультатПроверки = Новый Структура("Индекс, РезультатПроверкиПодписиПоМЧД", Подпись.Индекс,
			НовыйРезультатПроверкиДоверенностей);
		МодульМашиночитаемыеДоверенностиФНССлужебный.ДобавитьИнформациюМЧД(РезультатПроверки,
			Подпись.РезультатПроверкиПодписиПоМЧД);
		РезультатыПроверок.Добавить(РезультатПроверки);

	КонецЦикла;

	Возврат РезультатыПроверок;

КонецФункции

// Конец Локализация

// Заносит номер в регистр сведений НомераОтсканированныхФайлов.
//
// Параметры:
//   Владелец - ЛюбаяСсылка - владелец файла.
//   НовыйНомер -  Число  - максимальный номер для сканирования.
//
Процедура ЗанестиМаксимальныйНомерДляСканирования(Владелец, НовыйНомер) Экспорт
	
	// Подготовить структуру отбора по измерениям.
	СтруктураОтбора = Новый Структура;
	СтруктураОтбора.Вставить("Владелец", Владелец);

	НачатьТранзакцию();
	Попытка
		Блокировка = Новый БлокировкаДанных;
		ЭлементБлокировки = Блокировка.Добавить("РегистрСведений.НомераОтсканированныхФайлов");
		ЭлементБлокировки.УстановитьЗначение("Владелец", Владелец);
		Блокировка.Заблокировать();   		
		
		// Получить структуру с данными ресурсов записи.
		СтруктураРесурсов = РегистрыСведений.НомераОтсканированныхФайлов.Получить(СтруктураОтбора);
		   
		// Получить максимальный номер из регистра.
		Номер = СтруктураРесурсов.Номер;
		Если НовыйНомер <= Номер Тогда // Кто-то другой уже записал бОльший номер.
			ОтменитьТранзакцию();
			Возврат;
		КонецЕсли;

		Номер = НовыйНомер;
		УстановитьПривилегированныйРежим(Истина);
		
		// Запишем новый номер в регистр.
		НаборЗаписей = РегистрыСведений.НомераОтсканированныхФайлов.СоздатьНаборЗаписей();

		НаборЗаписей.Отбор.Владелец.Установить(Владелец);

		НоваяЗапись = НаборЗаписей.Добавить();
		НоваяЗапись.Владелец = Владелец;
		НоваяЗапись.Номер = Номер;

		НаборЗаписей.Записать();

		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		ВызватьИсключение;
	КонецПопытки;

КонецПроцедуры

Функция ПоместитьФайлыВоВременноеХранилище(Параметры) Экспорт

	Результат = Новый Массив;
	Для Каждого ФайлВложение Из Параметры.МассивФайлов Цикл
		РаботаСФайламиСлужебный.СформироватьСписокФайловДляОтправкиПоПочте(Результат, ФайлВложение,
			Параметры.ИдентификаторФормы);
	КонецЦикла;
	Возврат Результат;

КонецФункции

///////////////////////////////////////////////////////////////////////////////////
// Заполняет в табличном или офисном документе штамп электронной подписи.

Функция ДокументСоШтампом(Знач Файл) Экспорт

	Расширение = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Файл, "Расширение");

	Если Расширение = "mxl" Тогда
		ДанныеФайла    = РаботаСФайлами.ДанныеФайла(Файл);
		ВременныйФайл = ПолучитьИмяВременногоФайла(".mxl");
		ДвоичныеДанные = ПолучитьИзВременногоХранилища(ДанныеФайла.СсылкаНаДвоичныеДанныеФайла); // ДвоичныеДанные
		ДвоичныеДанные.Записать(ВременныйФайл);

		ТабличныйДокумент = Новый ТабличныйДокумент;
		ТабличныйДокумент.Прочитать(ВременныйФайл);

		УдалитьФайлы(ВременныйФайл);

		МодульЭлектроннаяПодпись = ОбщегоНазначения.ОбщийМодуль("ЭлектроннаяПодпись");

		ПараметрыШтампа = Новый Структура;
		ПараметрыШтампа.Вставить("ТекстОтметки", "");
		ПараметрыШтампа.Вставить("Логотип");

		ЭлектронныеПодписи = МодульЭлектроннаяПодпись.УстановленныеПодписи(Файл);
		ВладелецФайла = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Файл, "ВладелецФайла");

		СведенияОФайле = Новый Структура;
		СведенияОФайле.Вставить("ВладелецФайла", ВладелецФайла);

		Штампы = Новый Массив;
		Для Каждого Подпись Из ЭлектронныеПодписи Цикл
			Сертификат = Подпись.Сертификат;
			СертификатКриптографии = Новый СертификатКриптографии(Сертификат.Получить());
			РаботаСФайламиПереопределяемый.ПриПечатиФайлаСоШтампом(ПараметрыШтампа, СертификатКриптографии);

			Штамп = МодульЭлектроннаяПодпись.ШтампВизуализацииЭлектроннойПодписи(СертификатКриптографии,
				Подпись.ДатаПодписи, ПараметрыШтампа.ТекстОтметки, ПараметрыШтампа.Логотип);
			Штампы.Добавить(Штамп);
		КонецЦикла;

		МодульЭлектроннаяПодпись.ДобавитьШтампыВТабличныйДокумент(ТабличныйДокумент, Штампы);

		Возврат ТабличныйДокумент;
	ИначеЕсли Расширение = "docx" Тогда
		ДанныеФайла    = РаботаСФайлами.ДанныеФайла(Файл);
		МодульЭлектроннаяПодпись = ОбщегоНазначения.ОбщийМодуль("ЭлектроннаяПодпись");
		ЭлектронныеПодписи = МодульЭлектроннаяПодпись.УстановленныеПодписи(Файл);
		МодульУправлениеПечатью = ОбщегоНазначения.ОбщийМодуль("УправлениеПечатью");
		МодульУправлениеПечатью.ДобавитьШтампыВОфисныйДокумент(ДанныеФайла.СсылкаНаДвоичныеДанныеФайла,
			ЭлектронныеПодписи);

		Возврат ДанныеФайла.СсылкаНаДвоичныеДанныеФайла;
	Иначе
		Возврат Неопределено;
	КонецЕсли;

КонецФункции


// Проверяет наличие файла на компьютере.
//
// Параметры:
//   ПрисоединенныйФайл - ОпределяемыйТип.ПрисоединенныйФайл - проверяемый элемент справочника с файлом.
//
// Возвращаемое значение:
//   Булево
//
Функция ПрисоединенныйФайлНаходитсяНаДиске(Знач ПрисоединенныйФайл)

	ОбщегоНазначенияКлиентСервер.ПроверитьПараметр("РаботаСФайлами.ДвоичныеДанныеФайла", "ПрисоединенныйФайл",
		ПрисоединенныйФайл, Метаданные.ОпределяемыеТипы.ПрисоединенныйФайл.Тип);

	ФайлОбъект = РаботаСФайламиСлужебный.ФайлОбъект(ПрисоединенныйФайл);
	Если (ФайлОбъект = Неопределено Или ФайлОбъект.ЭтоГруппа) Тогда
		Возврат Ложь;
	КонецЕсли;

	УстановитьОтключениеБезопасногоРежима(Истина);
	УстановитьПривилегированныйРежим(Истина);

	Если ФайлОбъект.ПометкаУдаления Тогда
		Возврат Ложь;
	КонецЕсли;

	Если ФайлОбъект.ТипХраненияФайла = Перечисления.ТипыХраненияФайлов.ВИнформационнойБазе Тогда

		Результат = РаботаСФайлами.ХранилищеФайлаИзИнформационнойБазы(ФайлОбъект.Ссылка);
		Если Результат <> Неопределено Тогда
			Результат = Результат.Получить();
			Если Результат <> Неопределено Тогда
				Возврат Истина;
			КонецЕсли;
		КонецЕсли;

		Возврат Ложь;

	Иначе
		Возврат РаботаСФайламиВТомахСлужебный.ПрисоединенныйФайлНаходитсяНаДиске(ПрисоединенныйФайл);
	КонецЕсли;
КонецФункции

Функция ОбъединитьИзображенияВTifФайл(Знач Изображения) Экспорт
	ОбрабатываемаяКартинка = Новый ОбрабатываемаяКартинка(Изображения, ФорматКартинки.TIFF);
	Возврат ОбрабатываемаяКартинка.ПолучитьКартинку();
КонецФункции

Функция НачалоТекущегоСеанса() Экспорт
	Сеанс = ПолучитьТекущийСеансИнформационнойБазы();
	Возврат Сеанс.НачалоСеанса;
КонецФункции

Функция ТехническаяИнформацияОВерсияхПодсистемИРасширениях() Экспорт

	Возврат СтандартныеПодсистемыСервер.ТехническаяИнформацияОВерсияхПодсистемИРасширениях();

КонецФункции

Функция ПараметрыЛогирования(ИдентификаторКлиента) Экспорт
	Результат = Новый Структура;
	Результат.Вставить("ДатаНачалаЛогированияСканирования", ОбщегоНазначения.ХранилищеОбщихНастроекЗагрузить(
		"КомпонентаСканирования", "ДатаНачалаЛогированияСканирования", Дата(1, 1, 1)));
	Результат.Вставить("ИмяЛогФайла", ОбщегоНазначения.ХранилищеОбщихНастроекЗагрузить("КомпонентаСканирования",
		"ИмяЛогФайла", Неопределено));
	Результат.Вставить("КаталогЖурналаСканирования", ОбщегоНазначения.ХранилищеОбщихНастроекЗагрузить(
		"НастройкиСканирования/КаталогЖурналаСканирования", ИдентификаторКлиента, Неопределено));
	Результат.Вставить("ИспользоватьКаталогЖурналаСканирования", ОбщегоНазначения.ХранилищеОбщихНастроекЗагрузить(
		"НастройкиСканирования/ИспользоватьКаталогЖурналаСканирования", ИдентификаторКлиента, Ложь));
	Возврат Результат;
КонецФункции

// Возвращаемое значение:
//  Структура:
//   * ЖурналРегистрации - ДвоичныеДанные - данные выгрузки журнала регистрации
//   * ТехническаяИнформацияОВерсияхПодсистемИРасширениях - Строка
//   * ИмяЛогФайла - Строка - имя файла журнала, используемое компонентой сканирования
//
Функция ТехническаяИнформация() Экспорт

	Результат = Новый Структура;
	СобытиеЖурналаСканирования = НСтр("ru='Сканирование изображений'", ОбщегоНазначения.КодОсновногоЯзыка());

	СобытияОтбора = Новый Массив;
	СобытияОтбора.Добавить(СобытиеЖурналаСканирования + "." + "ПолучитьУстройства.Старт");
	СобытияОтбора.Добавить(СобытиеЖурналаСканирования + "." + "ПолучитьУстройства.Результат");
	СобытияОтбора.Добавить(СобытиеЖурналаСканирования + "." + "ПолучитьУстройства");
	СобытияОтбора.Добавить(СобытиеЖурналаСканирования + "." + "ПолучитьНастройку.Старт");
	СобытияОтбора.Добавить(СобытиеЖурналаСканирования + "." + "ПолучитьНастройку.Результат");
	СобытияОтбора.Добавить(СобытиеЖурналаСканирования + "." + "ПолучитьНастройку");
	СобытияОтбора.Добавить(СобытиеЖурналаСканирования + "." + "ЕстьУстройства.Старт");
	СобытияОтбора.Добавить(СобытиеЖурналаСканирования + "." + "ЕстьУстройства.Результат");
	СобытияОтбора.Добавить(СобытиеЖурналаСканирования + "." + "ЕстьУстройства");
	СобытияОтбора.Добавить(СобытиеЖурналаСканирования + "." + "НачатьСканирование.Старт");
	СобытияОтбора.Добавить(СобытиеЖурналаСканирования + "." + "НачатьСканирование.Результат");
	СобытияОтбора.Добавить(СобытиеЖурналаСканирования + "." + "НачатьСканирование");
	СобытияОтбора.Добавить(СобытиеЖурналаСканирования + "." + "Версия");
	СобытияОтбора.Добавить(СобытиеЖурналаСканирования + "." + "СобытиеСканера");
	СобытияОтбора.Добавить(СобытиеЖурналаСканирования + "." + "СобытиеСканера.ImageAcquired");
	СобытияОтбора.Добавить(СобытиеЖурналаСканирования + "." + "СобытиеСканера.EndBatch");
	СобытияОтбора.Добавить(СобытиеЖурналаСканирования + "." + "СобытиеСканера.UserPressedCancel");
	СобытияОтбора.Добавить(СобытиеЖурналаСканирования + "." + "LogFilePath.УстановкаЗначения");
	СобытияОтбора.Добавить(СобытиеЖурналаСканирования + "." + "LogFilePath.ЗначениеУстановлено");
	СобытияОтбора.Добавить(СобытиеЖурналаСканирования + "." + "LogFilePath");

	Отбор = Новый Структура("Событие", СобытияОтбора);
	Отбор.Вставить("ДатаНачала", ТекущаяДатаСеанса() - 600);
	
	УстановитьОтключениеБезопасногоРежима(Истина);
	УстановитьПривилегированныйРежим(Истина);
	Результат.Вставить("ЖурналРегистрации", ПолучитьИзВременногоХранилища(
		ЖурналРегистрации.ЖурналДляТехподдержки(Отбор, 200, Новый УникальныйИдентификатор)));
	УстановитьПривилегированныйРежим(Ложь);
	УстановитьОтключениеБезопасногоРежима(Ложь);
	
	Результат.Вставить("ТехническаяИнформацияОВерсияхПодсистемИРасширениях",
		СтандартныеПодсистемыСервер.ТехническаяИнформацияОВерсияхПодсистемИРасширениях());
	Результат.Вставить("ИмяЛогФайла", ОбщегоНазначенияВызовСервера.ХранилищеОбщихНастроекЗагрузить(
		"КомпонентаСканирования", "ИмяЛогФайла"));
	Возврат Результат;
КонецФункции

Процедура УстановитьПараметрыНачалаЛогирования(ИмяЛогФайла) Экспорт
	ОбщегоНазначенияВызовСервера.ХранилищеОбщихНастроекСохранить("КомпонентаСканирования", "ИмяЛогФайла", ИмяЛогФайла);
	ОбщегоНазначенияВызовСервера.ХранилищеОбщихНастроекСохранить("КомпонентаСканирования",
		"ДатаНачалаЛогированияСканирования", ТекущаяДатаСеанса());
КонецПроцедуры

Процедура ОчиститьРабочийКаталог(СсылкаПапки) Экспорт
	РаботаСФайламиСлужебный.ОчиститьРабочийКаталог(СсылкаПапки);
КонецПроцедуры

#КонецОбласти